класс, использующий глобальную внешнюю переменную const, которая определяется с помощью внутренней связи

StackOverflow https://stackoverflow.com//questions/21065112

Вопрос

У меня такая ситуация:

// Test.h
extern const int param;
class Test
{
private:
    int i;
public:
    int foo();
};

и

// Test.cpp
#include "Test.h"
int Test::foo() { return param*10; }

и

// core.h
#include "Test.h"
const int param = 1; // should have internal linkage later in core.cpp
int do_stuff ();

и

// core.cpp
#include "core.h"
int do_stuff () { Test obj; return obj.foo(); }
int main() { return do_stuff(); }

Однако ошибки компоновщика нет.Как работает компоновщик см. Для Test.cpp в const int param который осуществляется через core.h, определенный в core.cpp имеющий внутреннюю связь (по умолчанию для определений const)?

Когда я перепишу ядро.вот так (измените две строки):

// core.h
const int param = 1;
#include "Test.h"
int do_stuff ();

появляется ошибка компоновщика из-за отсутствия param.А потом, когда я изменю это вот так:

// core.h
extern const int param = 1;
#include "Test.h"
int do_stuff ();

все снова работает.

Я подумал, что, возможно, в исходной ситуации есть автоматическая вставка класса Test внутри core.cpp, так что Test.cpp как бы не существует, а весь код находится в core.cpp, так что все работает.Но почему тогда это должно зависеть от изменения двух строк в core.h?

Это было полезно?

Решение

Ваше предположение о внутренней связи для определений const не всегда верно.Смотрите раздел "Стандарт" 3.5 Program linkage, стр.3 (Я цитирую N3690):

Имя, имеющее область пространства имен (3.3.6), имеет внутреннюю связь, если это имя

  • переменная, функция или шаблон функции, который явно объявлен статическим;или,

  • энергонезависимая переменная, которая явно объявлена const или constexpr и ни extern, ни ранее было заявлено, что он имеет внешнюю связь;или

  • информационный член анонимного профсоюза.

Итак, для первого случая param имеет внешнюю связь, и все в порядке.

Для второго случая существует внутренняя ссылка param в core.cpp, но есть еще один заявленный-только param имеющий внешнюю связь, но не имеющий определения.

В третьем случае есть один param снова.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top