использование статического const int в структуре / классе - PullRequest
10 голосов
/ 21 августа 2009
struct A {
    static const int a = 5;

    struct B {
       static const int b = a;
    };

 };

 int main() {
   return A::B::b;
 }

Приведенный выше код компилируется. Однако, если вы пойдете по книге Effective C ++ Скотта Майерса (стр. 14); Нам нужно определение для в дополнение к объявлению. Кто-нибудь может объяснить, почему это исключение?

Ответы [ 4 ]

19 голосов
/ 21 августа 2009

По действительно педантичным правилам, да, ваш код нуждается в определении для этого статического целого числа. Но по практическим правилам и тому, что реализуют все компиляторы, потому что так предназначены правила C ++ 03 - нет, вам не нужно определение.

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

В вашем операторе return значение члена сразу же читается, поэтому вы можете опустить определение целочисленного члена статической константы, если это единственное его использование. Однако следующая ситуация требует определения:

struct A {
    static const int a = 5;

    struct B {
       static const int b = a;
    };

 };

 int main() {
   int *p = &A::B::b;
 }

Здесь не читается значение - вместо этого берется его адрес. Таким образом, цель стандарта C ++ 03 состоит в том, что вы должны предоставить определение для члена, как показано ниже в некотором файле реализации.

const int A::B::b;

Обратите внимание, что действительные правила , представленные в Стандарте C ++ 03, говорят, что определение не требуется только в том случае, если переменная используется, когда константное выражение требуется . Однако это правило, если оно строго соблюдается, является слишком строгим. Это позволит вам только опустить определение для ситуации, подобной измерениям массива, но потребует определения в случаях, таких как оператор возврата. Соответствующее сообщение о дефекте здесь .

Формулировка C ++ 0x была обновлена, чтобы включить разрешение этого дефекта и разрешить ваш код в том виде, как он написан.

19 голосов
/ 21 августа 2009

Компиляторы C ++ позволяют статическим целым числам const (и только целым числам) иметь свое значение, указанное в том месте, где они объявлены. Это связано с тем, что переменная по сути не нужна и живет только в коде (обычно она компилируется).

Другие типы переменных (такие как static const char *) обычно не могут быть определены там, где они объявлены, и требуют отдельного определения.

Для более подробного объяснения, поймите, что для доступа к глобальной переменной обычно требуется сделать ссылку на адрес в коде более низкого уровня. Но ваша глобальная переменная представляет собой целое число, размер которого обычно равен размеру адреса, и компилятор понимает, что он никогда не изменится, поэтому зачем добавлять абстракцию указателя?

2 голосов
/ 07 сентября 2009

Однако, если вы попробуете троичный операнд без «определения» статических констант, вы получите ошибку компоновщика в GCC 4x:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13795

Таким образом, хотя конструкции, подобные int k = A::CONSTVAL;, являются недопустимыми в текущем стандарте, они поддерживаются. Но троичного операнда нет. Некоторые операторы более равны, чем другие, если вы понимаете мой дрейф :) 1007 *

Так много для "слабых" правил. Я предлагаю вам написать код, соответствующий стандарту, если вы не хотите сюрпризов.

0 голосов
/ 21 августа 2009

Как правило, большинство (и недавних) компиляторов C ++ допускают статические константы

Тебе просто повезло, а может и нет. Попробуйте более старый компилятор, такой как gcc 2.0, и он сильно накажет вас сообщением об ошибке "меньше чем красиво".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...