Разница между созданием объекта с помощью() или без
Я просто столкнулся с проблемой
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