Costruttore predefinito con parentesi vuote
-
05-07-2019 - |
Domanda
C'è qualche buona ragione per cui un set vuoto di parentesi tonde (parentesi) non è valido per chiamare il costruttore predefinito in C ++?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
Mi sembra di digitare " () " automaticamente ogni volta. C'è una buona ragione per cui questo non è permesso?
Soluzione
Analisi più irritante
Questo è correlato a ciò che è noto come l'analisi più irritante di "C ++". Fondamentalmente, tutto ciò che può essere interpretato dal compilatore come una dichiarazione di funzione verrà interpretato come una dichiarazione di funzione.
Un'altra istanza dello stesso problema:
std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());
v
viene interpretato come una dichiarazione di funzione con 2 parametri.
La soluzione alternativa è aggiungere un'altra coppia di parentesi:
std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());
Oppure, se si dispone di C ++ 11 e inizializzazione elenco (nota anche come inizializzazione uniforme) disponibile:
std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};
In questo modo, non è possibile interpretarlo come una dichiarazione di funzione.
Altri suggerimenti
Perché è considerato come la dichiarazione di una funzione:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
La stessa sintassi viene utilizzata per la dichiarazione di funzione - ad es. la funzione oggetto
, non prendendo parametri e restituendo MyObject
Perché il compilatore pensa che sia una dichiarazione di una funzione che non accetta argomenti e restituisce un'istanza MyObject.
Suppongo che il compilatore non saprebbe se questa affermazione:
Oggetto MyObject ();
è una chiamata del costruttore o un prototipo di funzione che dichiara una funzione denominata oggetto con tipo di ritorno MyObject e senza parametri.
Puoi anche usare il modo più dettagliato di costruire:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
In C ++ 0x questo consente anche auto
:
auto object1 = MyObject();
auto object2 = MyObject(object1);
Come accennato più volte, è una dichiarazione. È così per la compatibilità con le versioni precedenti. Una delle molte aree del C ++ che sono sciocche / incoerenti / dolorose / fasulle a causa della sua eredità.
Da n4296 [dcl.init]:
[Nota:
Poiché()
non è consentito dalla sintassi per inizializzatore ,X a ();
non è la dichiarazione di un oggetto di classe X, ma il dichiarazione di una funzione non prendendo argomenti e restituendo una X. form () è consentito in alcuni altri contesti di inizializzazione (5.3.4, 5.2.3, 12.6.2).
& # 8212; nota di fine]
Come hanno detto gli altri, è una dichiarazione di funzione. Dal C ++ 11 puoi usare l'inizializzazione del controvento se hai bisogno di vedere il qualcosa vuoto che ti dice esplicitamente che viene usato un costruttore predefinito.
Jedi luke{}; //default constructor