Differenza tra la creazione dell’object con () o senza

Ho appena incontrato il problema

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

quando si tenta di compilare una semplice applicazione qt:

 #include  #include "gui/MainGUIWindow.h" int main( int argc, char** argv ) { QApplication app( argc, argv ); MainGUIWindow myWindow(); myWindow.show(); return app.exec(); } 

Ho risolto questo sostituendo

 MainGUIWindow myWindow(); 

di

 MainGUIWindow myWindow; 

ma non capisco la differenza. La mia domanda: qual è la differenza?

Saluti, Dirk

Le altre risposte indicano correttamente che la versione delle parentesi è in realtà una dichiarazione di funzione. Per capirlo in modo intuitivo, supponiamo di aver scritto MainGUIWindow f(); Sembra più una funzione, no? 🙂 La domanda più interessante è qual è la differenza tra

 MainGIUWindow* p = new MainGIUWindow; 

e

 MainGIUWindow* p = new MainGIUWindow(); 

La versione con parentesi è chiamata inizializzazione del valore, mentre la versione senza è definita inizializzazione di default. Per le classi non POD non c’è differenza tra i due. Per le strutture POD, tuttavia, i ruoli di inizializzazione del valore impostano tutti i membri su 0,

MY2C

Aggiunta: In generale, se un costrutto sintattico può essere interpretato sia come dichiarazione che come qualcos’altro, il compilatore risolve sempre l’ambiguità a favore della dichiarazione .

Il seguente:

 MainGUIWindow myWindow(); 

dichiara una funzione che non accetta argomenti e restituisce MainGUIWindow . Cioè myWindow è un nome di funzione.

 MainGUIWindow myWindow; 

d’altra parte crea un object myWindow di tipo MainGUIWindow .

La differenza è questa

 MainGUIWindow myWindow(); 

dichiara function myWindow , che non accetta parametri e restituisce MainGUIWindow , mentre

 MainGUIWindow myWindow; 

crea un nuovo object di tipo MainGUIWindow , chiamando il suo costruttore predefinito.

Una delle linee guida per i compilatori C ++, al fine di risolvere le ambiguità del codice, è: quando qualcosa può essere una dichiarazione di funzione, è una dichiarazione di funzione. Quindi, quando il compilatore vede:

 MainGUIWindow myWindow(); 

Comprende che stai dichiarando una funzione chiamata myWindow , che non accetta parametri e restituisce una MainGUIWindow . Ovviamente questo non è quello che vuoi.

Basta rimuovere la parentesi e starai bene:

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

Non ci sono problemi reali con la situazione che hai descritto. Togli le parentesi e il bingo! Funziona.

L ‘”analisi più irritante” è un problema molto più grande quando prende un singolo parametro e vuoi passare temporaneamente, ad esempio

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

non creerà un’istanza di Foo ma dichiarerà anche una funzione che accetta un puntatore a funzione, e questo spesso ti punge.

In C ++ ogni espressione che assomiglia a una dichiarazione di funzione è una dichiarazione di una funzione. Prendi in considerazione un campione più complesso che nella tua domanda:

 #include  struct X { X( int value ) : x(value) {} int x; }; struct Y { Y( const X& x ) : y(xx) {} int y; }; int main() { int test = 10; Y var( X(test) ); // 1 std::cout << var.y << std::endl; // 2 return 0; } 

A prima vista (1) è una dichiarazione della variabile locale var che dovrebbe essere inizializzata con un temporaneo di tipo X Ma sembra una dichiarazione di funzione per un compilatore e si otterrà un errore in (2):

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

Il compilatore considera che (1) è la funzione con nome var :

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

Ora, come dire al compilatore che non vuoi dichiarare una funzione? È ansible utilizzare parentesi aggiuntive come segue:

 Y var( (X(test)) ); 

Nel tuo caso MainGUIWindow myWindow() per il compilatore assomiglia alla dichiarazione di funzione:

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