使用()或不创建对象之间的区别

时间:2011-02-25 11:15:26

标签: c++ qt most-vexing-parse

我遇到了问题

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

尝试编译简单的qt-application时:

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

但我不明白其中的区别。我的问题:有什么区别?

此致 德克

7 个答案:

答案 0 :(得分:40)

其他答案正确地说明括号版本实际上是一个函数声明。要直观地理解它,假设你写了MainGUIWindow f();看起来更像是一个函数,不是吗? :) 更有趣的问题是

之间的区别是什么
MainGUIWindow* p = new MainGUIWindow;

MainGUIWindow* p = new MainGUIWindow();

带括号的版本称为值初始化,而没有括号的版本称为默认初始化。对于非POD类,两者之间没有区别。但是,对于POD结构,值初始化涉及将所有成员设置为0,

MY2C

补充:一般来说,如果某些句法结构可以被解释为声明和其他东西,编译器 总是解决歧义而支持声明 。 / p>

答案 1 :(得分:17)

以下内容:

MainGUIWindow myWindow();

声明一个不带参数的函数并返回MainGUIWindow。即myWindow是函数名称。

MainGUIWindow myWindow;
另一方面,

创建myWindow类型的对象MainGUIWindow

答案 2 :(得分:3)

区别在于,

MainGUIWindow myWindow(); 

声明函数myWindow,它不接受任何参数并返回MainGUIWindow,而

MainGUIWindow myWindow; 

创建MainGUIWindow类型的新对象,调用它的默认构造函数。

答案 3 :(得分:3)

为了解决代码歧义,C ++编译器的一个指导原则是:当某些东西可以是函数声明时,它是一个函数声明。所以当编译器看到:

MainGUIWindow myWindow();

它理解您正在声明一个名为myWindow的函数,该函数不接受任何参数并返回MainGUIWindow。显然这不是你想要的。

只需删除括号,您就可以了:

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

答案 4 :(得分:3)

您所描述的情况并没有真正的问题。你删除括号和宾果游戏!它有效。

“最令人烦恼的解析”是一个更大的问题,当它需要一个参数并且你想传递一个临时的,例如

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

Foo foo( Bar() );

不会创建Foo的实例,但也会声明一个带有函数指针的函数,而且这个函数经常会刺痛你。

答案 5 :(得分:0)

在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

答案 6 :(得分:-2)

此外,来自CppCon 2017:Louis Brandy“在Facebook上反复出现C ++错误”

std::unique_lock<std::mutex> (_mutex);

是一个名为“ _mutex”的锁的声明,该锁什么都没有锁。由于通常以后不需要与锁进行交互,因此很容易错过为其命名的可能性。

对于任何同时具有默认构造函数和更有用的带有一个参数的构造函数的RAII对象,这都是一个问题。