Конструктор по умолчанию с пустыми скобками
Есть ли веская причина, что пустой набор круглых скобок (скобки) недействителен для вызова конструктора по умолчанию в С++?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
Кажется, я набираю "()" автоматически каждый раз. Есть ли веская причина, по которой это не разрешено?
Ответы
Ответ 1
Самый неприятный синтаксический анализ
Это связано с тем, что называется "С++ most vexing parse". В принципе, все, что может быть интерпретировано компилятором как объявлением функции, будет интерпретироваться как объявление функции.
Другой экземпляр той же проблемы:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v
интерпретируется как объявление функции с двумя параметрами.
Обходной путь заключается в добавлении еще одной пары круглых скобок:
std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());
Или, если у вас есть С++ 11 и инициализация списка (также известная как равномерная инициализация):
std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};
При этом нет способа интерпретировать его как объявление функции.
Ответ 2
Потому что он рассматривается как объявление для функции:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
Ответ 3
Тот же синтаксис используется для объявления функции - например, функция object
, не принимающая никаких параметров и возвращающая MyObject
Ответ 4
Поскольку компилятор считает, что это объявление функции, которая не принимает аргументов и возвращает экземпляр MyObject.
Ответ 5
Вы также можете использовать более подробный способ построения:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
В С++ 0x это также позволяет auto
:
auto object1 = MyObject();
auto object2 = MyObject(object1);
Ответ 6
Я думаю, компилятор не знал бы, будет ли это утверждение:
Объект MyObject();
- это вызов конструктора или прототип функции, объявляющий функцию с именем object с возвращаемым типом MyObject и без параметров.
Ответ 7
Как уже упоминалось много раз, это декларация. Это так для обратной совместимости. Одна из многих областей С++, которая является тупой/непоследовательной/болезненной/фиктивной из-за ее наследия.
Ответ 8
От n4296 [dcl.init]:
[Примечание:
Поскольку ()
не разрешен синтаксисом для инициализатора, X a();
не является объявлением объекта класса X, но объявление функции, не принимающей аргументов и возвращающей X. form() разрешена в некоторых других контекстах инициализации (5.3.4, 5.2.3, 12.6.2).
- конец заметки]
С++ 11 Ссылка
С++ 14 Ссылка
Ответ 9
Как говорили другие, это объявление функции. Начиная с С++ 11 вы можете использовать инициализацию скобки, если вам нужно увидеть пустое то, что явно указывает вам, что используется конструктор по умолчанию.
Jedi luke{}; //default constructor