нестатические элементы данных и одно правило определения
Предпосылка
В соответствии с правилом одного определения, Как указано в стандарте C++14, я могу иметь определение одного и того же класса в каждой единице перевода, пока я следую правилам в 3.2.6. Это означает, что следующая программа может быть легальной:
//a_1.cpp
class A { //definition of A
int a; //definition of A::a
static int b; //declaration of A::b
int foo(); //declaration of A::foo();
int boo(){ return 42; }; //definition of A::boo() implicity inlined
};
//a_2.cpp
class A { //definition of A
int a; //definition of A::a
static int b; //declaration of A::b
int foo(); //declaration of A::foo();
int boo(){ return 42; }; //definition of A::boo() implicity inlined
};
Если я попытаюсь определить b
или foo()
, я, однако, ограничусь одним определением во всей программе, которое, как я полагаю, связано с утверждением в 3.2.4:
По этой причине плохо сформирована следующая программа:Каждая программа должна содержать ровно одно определение каждой нестрочной функции или переменной, которая используется odr в этой программе не требуется никакой диагностики.
//a_1.cpp
class A { //definition of A
int a; //definition of A::a
static int b; //declaration of A::b
int foo(); //declaration of A::foo();
int boo(){ return 42; }; //definition of A::boo() implicity inlined
};
int A::b;
//a_2.cpp
class A { //definition of A
int a; //definition of A::a
static int b; //declaration of A::b
int foo(); //declaration of A::foo();
int boo(){ return 42; }; //definition of A::boo() implicitly inlined
};
int A::b;
То же самое, если бы я попытался определить foo()
в обоих исходных файлах.
Я могу, однако, иметь несколько определений boo()
(по одному на единицу перевода), поскольку это не запрещено 3.2.4 и, фактически, явно разрешено 3.2.6:
Чтобы быть справедливым, 3.2.6 уточняет приведенное выше утверждение, добавляя несколько требований, среди которых сущность (в нашем случаеМожет быть более одного определения типа класса (пункт 9), типа перечисления (7.2), встроенной функции с внешняя связь (7.1.2), шаблон класса (пункт 14), шаблон нестатической функции (14.5.6), статический элемент данных шаблона класса (14.5.1.3), функции-члена шаблона класса (14.5.1.1) или специализации шаблона для которые некоторые параметры шаблона не указаны (14.7, 14.5.5) в программе при условии, что каждое определение появляется в другом единица перевода.
boo()
) должна определяться одной и той же последовательностью лексем в каждой единице перевода.
Вопрос
Как насчет нестатического элемента данных a
? Очевидно, что допускается несколько определений a
(в противном случае программа в верхней части моего вопроса не компилировалась бы), но это, по-видимому, запрещено 3.2.4 и не потворствует 3.2.6. Это просто деталь, не строго оговоренная в стандарте, или я что-то упустил?
Edit
Для тех, кто указал мне, что a
не определен, а просто объявлен, пожалуйста, рассмотрим этот пример, взятый прямо из стандарта C++14, 3.2.2:
struct X { // defines X
int x; // defines non-static data member x
static int y; // declares static data member y
X(): x(0) { } // defines a constructor of X
};
Пожалуйста, не думайте, что комментарии к приведенному выше коду не мои, а скопированы прямо из стандарта.
2 ответа:
[основной.защита.odr]/1:
Ни одна единица перевода не должна содержать более одного определения какой-либо переменной, функции, типа класса, типа перечисления или шаблона.
переменная определяется [basic]/6:
Таким образом, поскольку нестатический элемент данных не является переменной, функцией, классом, перечислением или шаблоном, то одно правило определения просто не применяется к нестатическим элементам данных.Переменнаявводится объявлением ссылки, отличной от нестатического элемента данных или объекта.