Разница между созданием объекта с () или без - PullRequest
17 голосов
/ 25 февраля 2011

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

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;

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

С уважением, Дирк

Ответы [ 6 ]

40 голосов
/ 25 февраля 2011

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

MainGUIWindow* p = new MainGUIWindow;

и

MainGUIWindow* p = new MainGUIWindow();

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

my2c

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

17 голосов
/ 25 февраля 2011

следующее:

MainGUIWindow myWindow();

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

MainGUIWindow myWindow;

, с другой стороны, создает объект myWindow типа MainGUIWindow.

3 голосов
/ 25 февраля 2011

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

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

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

Foo foo( Bar() );

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

3 голосов
/ 25 февраля 2011

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

MainGUIWindow myWindow();

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

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

MainGUIWindow myWindow; // Create an object called myWindow, of type MainGUIWindow
3 голосов
/ 25 февраля 2011

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

MainGUIWindow myWindow(); 

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

MainGUIWindow myWindow; 

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

0 голосов
/ 28 февраля 2011

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

#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
...