Вопрос

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

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

MyObject  object();  // error

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

Это было полезно?

Решение

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

Это связано с тем, что известно как «самый неприятный синтаксический анализ» в 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>{}};

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

Другие советы

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

int MyFunction(); // clearly a function
MyObject object(); // also a function declaration

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

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

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

  

MyObject object ();

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

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

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

В C ++ 0x это также допускает auto :

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

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

От n4296 [dcl.init]:

  

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

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

Jedi luke{}; //default constructor
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top