Конструктор по умолчанию с пустыми скобками - PullRequest
183 голосов
/ 08 октября 2008

Есть ли веская причина, по которой пустой набор круглых скобок (скобок) недопустим для вызова конструктора по умолчанию в C ++?

MyObject  object;  // ok - default ctor
MyObject  object(blah); // ok

MyObject  object();  // error

Кажется, я каждый раз набираю "()" автоматически. Есть ли веская причина, по которой это запрещено?

Ответы [ 9 ]

151 голосов
/ 08 октября 2008

Самый неприятный анализ

Это связано с тем, что известно как «самый неприятный синтаксический анализ C ++». По сути, все, что может быть интерпретировано компилятором как объявление функции, будет интерпретировано как объявление функции.

Еще один пример той же проблемы:

std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());

v интерпретируется как объявление функции с 2 параметрами.

Обходной путь - добавить еще пару скобок:

std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());

Или, если у вас есть C ++ 11 и инициализация списка (также известная как равномерная инициализация):

std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};

При этом никоим образом это не может быть интерпретировано как объявление функции.

95 голосов
/ 08 октября 2008

Поскольку это трактуется как объявление для функции:

int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
50 голосов
/ 08 октября 2008

Тот же синтаксис используется для объявления функции - например, функция object, не принимающая параметров и возвращающая MyObject

11 голосов
/ 08 октября 2008

Поскольку компилятор считает, что это объявление функции, которая не принимает аргументов и возвращает экземпляр MyObject.

7 голосов
/ 08 октября 2008

Вы также можете использовать более подробный способ построения:

MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);

В C ++ 0x это также позволяет auto:

auto object1 = MyObject();
auto object2 = MyObject(object1);
7 голосов
/ 08 октября 2008

Я думаю, компилятор не будет знать, если это утверждение:

MyObject object ();

является вызовом конструктора или прототипа функции, объявляющей функцию с именем объект с типом возврата MyObject и без параметров.

5 голосов
/ 08 октября 2008

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

4 голосов
/ 27 июня 2015

из n4296 [dcl.init]:

[Примечание:
Поскольку синтаксис для не разрешен (), , X a(); не является объявлением объекта класса X, но объявление функции без аргументов и возвращение X. form () разрешена в некоторых других контекстах инициализации (5.3.4, 5.2.3, 12.6.2).
—конечная записка]

1 голос
/ 19 октября 2017

Как говорили другие, это объявление функции. Начиная с C ++ 11 вы можете использовать фигурную инициализацию, если вам нужно увидеть пустое что-то , которое явно говорит вам об использовании конструктора по умолчанию.

Jedi luke{}; //default constructor
...