2014-01-11 3 views
1

меня такая ситуация:класс с использованием глобальной Экстерн константной переменной, которая определяется с внутренней связью

// 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 с внутренней связью (по умолчанию для определений констант)?

Когда я переписать core.h как это (изменить две строки):

// 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?

ответ

0

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

Пространство имен Объем имя, имеющий (3.3.6) имеет внутреннюю связь, если она является именем

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

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

  • член данных анонимного объединения.

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

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

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

+0

Спасибо за прекрасный ответ! – mb84