24

i just run into the problem

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

when trying to compile a simple 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();
}

I solved this by replacing

MainGUIWindow myWindow(); 

by

MainGUIWindow myWindow;

but I don't understand the difference. My question: What is the difference?

Regards, Dirk

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
Dirk
  • 1,789
  • 2
  • 21
  • 31
  • possible duplicate of [Do the parentheses after the type name make a difference with new?](http://stackoverflow.com/questions/620137/do-the-parentheses-after-the-type-name-make-a-difference-with-new) – fredoverflow Feb 25 '11 at 11:34
  • 1
    @FredOverflow This is not a duplicate of that issue, the case with new is different as Amen below has pointed out. I don't know if there is another issue somewhere it may be a duplicate of. – CashCow Feb 25 '11 at 11:43
  • 1
    before anyone else gets the wrong idea, this is *not* a duplicate. The titles are similar, but the questions are entirely different. One is about the different initalization rules in C++, the other is about why code intended to instantiate an object is instead parsed as a function declaration. – jalf Feb 25 '11 at 11:43
  • Actually, __this is a dupe__ of http://stackoverflow.com/questions/1424510/most-vexing-parse-why-doesnt-a-a-work – sbi Feb 25 '11 at 11:44
  • Better duplicate because this more closely matches this question: [Is no parentheses on a C++ constructor with no arguments a language standard?](http://stackoverflow.com/questions/2318650/is-no-parentheses-on-a-c-constructor-with-no-arguments-a-language-standard). This isn't really the most vexing parse, it's just a slightly vexing parse. – CB Bailey Mar 01 '11 at 08:05
  • Another duplicate: [Why is there no call to the constructor?](http://stackoverflow.com/questions/3810570/why-is-there-no-call-to-the-constructor) . – CB Bailey Mar 01 '11 at 08:06

7 Answers7

49

The other answers correctly state that the parentheses version is actually a function declaration. To understand it intuitively, suppose you wrote MainGUIWindow f(); Looks more like a function, doesn't it? :) The more interesting question is what is the difference between

MainGUIWindow* p = new MainGUIWindow;

and

MainGUIWindow* p = new MainGUIWindow();

The version with parentheses is called value-initialization, whereas the version without is called default-initialization. For non-POD classes there is no difference between the two. For POD-structs, however, value-initialization involves setting all members to 0,

my2c

Addition: In general, if some syntactic construct can be interpreted both as a declaration and something else, the compiler always resolves the ambiguity in favor of the declaration.

Dan Yard
  • 147
  • 1
  • 5
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 1
    This is called the "most vexing parse". – Zac Howland Feb 25 '11 at 11:32
  • The more vexing parse comes when you try to create an instance of a class that takes one member and you pass in what you think is a temporary, especially a problem when it has an implicit constructor – CashCow Feb 25 '11 at 11:42
  • Cong-rats and other rodents for crossing the 10k barrier, but this is a dupe. I suppose there's many "most vexing parse" questions out there. (I marked the first one that seemed a match.) – sbi Feb 25 '11 at 11:51
20

The following:

MainGUIWindow myWindow();

declares a function that takes no arguments and returns MainGUIWindow. I.e. myWindow is a function name.

MainGUIWindow myWindow;

on the other hand creates an object myWindow of type MainGUIWindow.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
4

The difference is, that

MainGUIWindow myWindow(); 

declares function myWindow, which takes no parameters and returns MainGUIWindow, whereas

MainGUIWindow myWindow; 

creates new object of type MainGUIWindow, calling it's default constructor.

nothrow
  • 15,882
  • 9
  • 57
  • 104
4

There is no real problems with the situation you have described. You remove the parentheses and bingo! it works.

The "most vexing parse" is a much bigger issue when it takes a single parameter and you want to pass in a temporary, eg

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

Foo foo( Bar() );

will not create an instance of a Foo but will also declare a function that takes a function-pointer, and this one really does often sting you.

CashCow
  • 30,981
  • 5
  • 61
  • 92
3

One of the guidelines for C++ compilers, in order to resolve code ambiguities, is: when something can be a function declaration, it is a function declaration. So when the compiler sees:

MainGUIWindow myWindow();

It understands you are declaring a function called myWindow, that takes no parameters and returns a MainGUIWindow. Obviously this is not what you want.

Just remove the parenthesis and you will be fine:

MainGUIWindow myWindow; // Create an object called myWindow, of type MainGUIWindow
Gorpik
  • 10,940
  • 4
  • 36
  • 56
0

In C++ every expression that looks like a function declaration is a declaration of a function. Consider more complex sample that in your question:

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

At first glance (1) is a declaration of the local variable var which should be initialized with a temporary of a type X. But this looks like a function declaration for a compiler and you will get an error in (2):

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

The compiler considers that (1) is the function with name var:

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

Now, how to say to the compiler that you do not want to declare a function? You could use additional parentheses as follows:

Y var( (X(test)) );  

In your case MainGUIWindow myWindow() for the compiler looks like function declaration:

MainGUIWindow    myWindow(        void                  )
^- return value  ^-function name  ^-type of an argument
Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
-1

Also, from CppCon 2017: Louis Brandy “Curiously Recurring C++ Bugs at Facebook”

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

Is a declaration of a lock named "_mutex" that locks nothing. Since you typically don't need to interact with locks later, it's very easy to miss giving it a name.

This is a problem for any RAII object that has both a default constructor and a more useful constructor that takes one argument.

Tayron Lee
  • 11
  • 1