Как предотвратить инициализацию по умолчанию для константной переменной с типом класса - PullRequest
5 голосов
/ 18 ноября 2011

У меня есть собственный класс, который я хочу вести себя как встроенный тип.

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

Вот сравнение int и моего класса foo:

int a;              // Valid
int a = 1;          // Valid
const int a = 1;    // Valid
const int a;        // Error

foo a;              // Valid
foo a = 1;          // Valid
const foo a = 1;    // Valid
const foo a;        // Should cause an error, but it compiles

Как видите, мне нужно предотвратить

const foo a;

от компиляции.

Есть идеи от гуру C ++?

Ответы [ 2 ]

6 голосов
/ 18 ноября 2011

Он компилируется, только если у него есть конструктор по умолчанию, и компилируется, потому что он у него есть, что означает, что он инициализирован.Если вы не хотите, чтобы эта строка компилировалась, просто отключите конструктор по умолчанию (это также сделает foo a; ошибкой как нежелательный побочный эффект).Без определения foo или того, что вы хотите сделать, это насколько я могу получить.

Я не думаю, что есть какой-то способ достичь того, что вы хотите (т.е. разрешить неконстантныйпеременная должна быть инициализирована по умолчанию, при этом компиляция константной версии не будет выполнена и разрешены другие варианты использования - для этого требуются конструкторы)

3 голосов
/ 18 ноября 2011

Правила C ++ просто говорят, что инициализация по умолчанию (например, new T;) и инициализация значения (например, new T();) одинаковы для объектов типа класса, но не для объектов фундаментального типа.

Вы ничего не можете сделать, чтобы "преодолеть" это различие.Это фундаментальная часть грамматики.Если ваш класс является инициализируемым по значению, то он также инициализируется по умолчанию.

Для классов без каких-либо пользовательских конструкторов существует своего рода исключение: в этом случае инициализация членов выполняется рекурсивно (поэтомуесли вы по умолчанию инициализируете объект, он попытается инициализировать по умолчанию все члены), и это не удастся, если какой-либо из классов члены сами по себе являются фундаментальными, или опять-таки такого типа.

Например, рассмотрим следующие два класса:

struct Foo { int a; int b; };
struct Goo { int a; int b; Goo(){} };

//const Foo x; // error
const Goo y;   // OK

Неявный конструктор для Foo отклонен, поскольку он не инициализирует фундаментальные члены.Однако y успешно инициализируется по умолчанию, а y.a и y.b теперь "намеренно оставлены пустыми".

Но если в вашем классе нет пользовательских конструкторов, эта информация будет выигранатебе не поможетВы не можете "переслать" тип инициализации члену (например, Foo() : INIT_SAME_AS_SELF(a), b() { }).

...