Почему множественное определение глобальной переменной const разрешено в C ++, а не в C? - PullRequest
28 голосов
/ 30 мая 2011

Множественное определение глобальной переменной не разрешено в C или C ++ из-за правила One Definition Rule. Однако в C ++ глобальная переменная const может быть определена в нескольких единицах компиляции без ошибок. Это не то же самое, что в C.

Почему C ++ допускает это, а C - нет? Почему использование и поведение const global отличается от неконстантного global таким образом в C ++ по сравнению с C? Что происходит под покровом C ++ и C относительно const?

Например, это разрешено в C ++, но неправильно в C:

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;
int main()
{
    cout << Foo << endl;
    return 0;
}

И это нормально с C, но неправильно с C ++:

// Foo.cpp
const int Foo = 99;

// Main.cpp
extern const int Foo;
int main()
{
    cout << Foo << endl;
    return 0;
}

Ответы [ 6 ]

28 голосов
/ 30 мая 2011
// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;

const переменная в области именного пространства имеет внутреннюю связь. Таким образом, они в основном две разные переменные. Переопределения нет.

Из @ комментария Дэвида, 3.5 / 3 [basic.link]:

Имя, имеющее область имен (3.3.5) имеет внутреннюю связь , если это имя из
- объект, ссылка, функция или шаблон функции, который явно объявленный статический или
- объект или ссылка, явно объявленная const и ни одно явно не заявлено extern или ранее заявлено, что внешняя связь ; или
- член данных анонимного союза.


Во втором случае вы должны делать это (правильно):

//Foo.h
extern const int Foo; //use extern here to make it have external linkage!

// Foo.cpp
#include "Foo.h"
const int Foo = 99; //actual definition goes here

// Main.cpp
#include "Foo.h"
int main()
{
   cout << Foo << endl;
}
7 голосов
/ 30 мая 2011

Я думаю, вы спрашиваете об обосновании, а не о конкретном языковом правиле, которое позволяет это.

Основанием для этого является то, что это делает const переменными намного проще в использовании. Это дает типичную замену для одного общего использования #define.

Вместо #define MAX_COUNT 211 вы можете использовать const int max_count = 211; точно таким же образом, например, файл общего заголовка, не беспокоясь о том, куда поместить одно определение.

Вы не можете юридически изменить значение объекта const, поэтому нет видимой разницы между наличием одного объекта и нескольких объектов с одинаковым значением.

Поскольку вы можете поместить определение const объекта в заголовочный файл, компилятору будет просто использовать это значение непосредственно на этапе компиляции, не прибегая к такой оптимизации, чтобы отложить на исправление во время компоновки.

6 голосов
/ 30 мая 2011

По сути, в C ++ const, нелокальные переменные являются подлинными константными выражениями или constexpr.Это допускает множество вещей, например TMP.

const int five = 5;
int main() {
    int x[five];
    std::array<int, five> arr;
}

В C они являются просто переменной, которую нельзя изменить.То есть

const int five = 5;
int main() {
    int x[five]; // Technically, this is a variable length array
}

вполне эквивалентно

int five = 5;
int main() {
    int x[five];
}

По сути, C ++ переводит некоторые виды переменных const в новую категорию, constexpr, тогда как в C этоне существует, и это просто переменные, которые оказываются неизменяемыми.

3 голосов
/ 30 мая 2011
0 голосов
/ 22 октября 2013

Мой обходной путь объявлял это как:

static classfoo foo;

это работало в моей ситуации.

0 голосов
/ 04 мая 2012

Почему англичане пишут COLOR, тогда как американцы пишут COLOR?

Это два разных языка из одной базы, но у них нет одинаковых правил.

C и C ++ одинаковы.Если бы они не были разными, их обоих назвали бы одним и тем же.

...