Разница между созданием объекта с помощью() или без

Я просто столкнулся с проблемой

error: request for member ‘show’ in ‘myWindow’, which is of non-class type ‘MainGUIWindow()’

при попытке скомпилировать простое qt-приложение:

#include <QApplication>
#include "gui/MainGUIWindow.h"


int main( int argc, char** argv )
{
  QApplication app( argc, argv );


  MainGUIWindow myWindow();
  myWindow.show();


  return app.exec();
}

Я решил это, заменив

MainGUIWindow myWindow(); 

по

MainGUIWindow myWindow;

но я не понимаю разницы. Мой вопрос: В чем разница?

С уважением, Dirk

Ответы

Ответ 1

В других ответах правильно указано, что версия круглых скобок является фактически объявлением функции. Чтобы понять это интуитивно, предположим, что вы написали MainGUIWindow f(); Выглядит больше как функция, не так ли?:) Более интересный вопрос заключается в том, какая разница между

MainGIUWindow* p = new MainGIUWindow;

и

MainGIUWindow* p = new MainGIUWindow();

Версия с круглыми скобками называется инициализацией значений, тогда как версия без называется инициализацией по умолчанию. Для классов, отличных от POD, между ними нет различия. Однако для POD-структур инициализация значений включает в себя установку всех членов в 0,

my2c

Дополнение: В общем случае, если какая-либо синтаксическая конструкция может быть интерпретирована как декларация и что-то еще, компилятор всегда разрешает двусмысленность в пользу объявления.

Ответ 2

Следующее:

MainGUIWindow myWindow();

объявляет функцию, которая не принимает аргументов и возвращает MainGUIWindow. То есть myWindow - это имя функции.

MainGUIWindow myWindow;
С другой стороны,

создает объект myWindow типа MainGUIWindow.

Ответ 3

Разница в том, что

MainGUIWindow myWindow(); 

объявляет функцию myWindow, которая не принимает параметров и возвращает MainGUIWindow, тогда как

MainGUIWindow myWindow; 

создает новый объект типа MainGUIWindow, вызывая его конструктор по умолчанию.

Ответ 4

Одно из рекомендаций для компиляторов С++ для устранения неоднозначности кода - это: когда что-то может быть объявлением функции, это объявление функции. Поэтому, когда компилятор видит:

MainGUIWindow myWindow();

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

Просто удалите скобку, и все будет хорошо:

MainGUIWindow myWindow; // Create an object called myWindow, of type MainGUIWindow

Ответ 5

Нет реальных проблем с описанной ситуацией. Вы удаляете круглые скобки и бинго! он работает.

"Самый неприятный синтаксический анализ" - это гораздо более серьезная проблема, когда он принимает один параметр и вы хотите передать временный, например

class Foo
{
public:
 explicit Foo( const Bar& bar );
};

Foo foo( Bar() );

не создаст экземпляр Foo, но также объявит функцию, которая принимает указатель на функцию, и это действительно часто заставляет вас.

Ответ 6

В С++ каждое выражение, которое выглядит как объявление функции, является объявлением функции. Рассмотрим более сложный образец, который в вашем вопросе:

#include <iostream>

struct X
{
  X( int value ) : x(value) {}
  int x;
};

struct Y
{
  Y( const X& x ) : y(x.x) {}
  int y;
};

int main()
{
  int test = 10;
  Y var( X(test) );                 // 1
  std::cout << var.y << std::endl;  // 2

  return 0;
}

На первый взгляд (1) есть объявление локальной переменной var, которая должна быть инициализирована временным типом X. Но это выглядит как объявление функции для компилятора, и вы получите ошибку в (2):

 error: request for member ‘y’ in ‘var’, which is of non-class type ‘Y(X)’

Компилятор считает, что (1) является функцией с именем var:

Y                var(             X                     test            );
^- return value  ^-function name  ^-type of an argument ^-argument name

Теперь, как сказать компилятору, что вы не хотите объявлять функцию? Вы можете использовать дополнительные скобки следующим образом:

Y var( (X(test)) );  

В вашем случае MainGUIWindow myWindow() для компилятора выглядит как объявление функции:

MainGUIWindow    myWindow(        void                  )
^- return value  ^-function name  ^-type of an argument