Разве скобки на конструкторе без аргументов не являются стандартом языка? - PullRequest
48 голосов
/ 23 февраля 2010

Я компилировал программу на C ++ в Cygwin, используя g ++, и у меня был класс, конструктор которого не имел аргументов.У меня были строки:

MyClass myObj();
myObj.function1();

И при попытке его скомпилировать, я получил сообщение:

error: request for member 'function1' in 'myObj', which is of non-class type 'MyClass ()()'

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

MyClass myObj;

Могу поклясться, что раньше я делал пустые объявления конструктора с круглыми скобками в C ++.Возможно, это ограничение используемого мной компилятора или действительно ли языковой стандарт говорит, что не используйте скобки для конструктора без аргументов?

Ответы [ 8 ]

54 голосов
/ 23 февраля 2010

Хотя MyClass myObj(); может быть проанализирован как определение объекта с пустым инициализатором или объявлением функции, языковой стандарт указывает, что неоднозначность всегда разрешается в пользу объявления функции. Инициализатор пустых скобок разрешен в других контекстах, например в выражении new или построении значения, инициализированного , временным.

50 голосов
/ 23 февраля 2010

Это называется самой неприятной проблемой разбора. Когда парсер видит

MyClass myObj();

Он думает, что вы объявляете функцию с именем myObj, которая не имеет параметров и возвращает MyClass.

Чтобы обойти это, используйте:

MyClass myObj;
19 голосов
/ 23 февраля 2010

Я нашел это в стандарте C ++ (§8.5.8):

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

[Примечание: поскольку () не разрешено синтаксис для инициализатора,

X a ();

не является объявлением объекта класса X, но объявление функции, не принимающей аргумент и возвращая X. Форма () разрешено в некоторых других контексты инициализации (5.3.4, 5.2.3, 12.6.2). —Конечная записка]

10 голосов
/ 23 февраля 2010

Это довольно известная проблема, и она не зависит от компилятора. По сути, вы делали объявление функции, возвращающей тип MyObj. Не удивительно, что вы не могли вызвать его конструктор. См. C ++ faq lite для хорошего объяснения

4 голосов
/ 23 февраля 2010
MyClass myObj();

Это анализируется как объявление функции, функция называется myObj, не принимает аргументов и возвращает объект MyClass. Я никогда не видел, чтобы компилятор принимал это. С другой стороны, MyClass* myPtr = new MyClass(); приемлемо, может быть, это вас смутило?

4 голосов
/ 23 февраля 2010

Еще один самый неприятный разбор хита. См. Например Функция сортировки не работает с объектом функции, созданным в стеке?

3 голосов
/ 23 февраля 2010

Ваша строка заставляет компилятор думать, что вы объявляете функцию с именем myObj, которая не принимает аргументов и возвращает MyClass. Это разрешение двусмысленности действительно раздражает.

1 голос
/ 23 февраля 2010

Стандарт не требует скобок.

int* x = new int;

является допустимым синтаксисом.

В вашем случае myclass myobj(); - это прототип функции. Принимая во внимание, что myclass myobj; является переменной.

...