2010-02-23 6 views
44

Kompilowałem program C++ w Cygwin używając g ++ i miałem klasę, której konstruktor nie miał argumentów. Miałem linie:Czy nawiasy w konstruktorze bez argumentów są standardem językowym?

MyClass myObj(); 
myObj.function1(); 

A kiedy próbuje go skompilować, mam komunikat:

błąd: wniosek o członka „Function1” in „myObj”, która jest typu non-klasa „MojaKlasa()() ''

Po drobnych badaniach odkryłem, że poprawka miała zmienić pierwszą linię na MyClass myObj;

Mogę przysiąc, że wcześniej wykonałem puste deklaracje konstruktorów z nawiasami w C++. Czy jest to prawdopodobnie ograniczenie używanego przeze mnie kompilatora, czy też rzeczywiście standard językowy nie używa nawiasów dla konstruktora bez argumentów?

Odpowiedz

49

Chociaż MyClass myObj(); może być analizowany jako definicja obiektu z pustym inicjatorem lub deklaracją funkcji, standard językowy określa, że ​​niejednoznaczność jest zawsze rozstrzygnięta na korzyść deklaracji funkcji. Pusty inicjator nawiasów jest dozwolony w innych kontekstach, np. w wyrażeniu new lub utworzeniu wartości tymczasowejzainicjowanej wartością.

1

Standard nie wymaga nawiasów.

int* x = new int; 

jest prawną składnią.

W twoim przypadku myclass myobj(); jest prototypem funkcji. Natomiast myclass myobj; jest zmienną.

3

Twoja linia sprawia, że ​​kompilator myśli, że deklarujesz funkcję o nazwie myObj, która nie przyjmuje żadnych argumentów i zwraca wartość MyClass. To rozwiązanie dwuznaczności jest rzeczywiście denerwujące.

10

Jest to dość znany problem i nie jest zależny od kompilatora. Zasadniczo, to co robiłeś, to deklarowanie funkcji zwracającej typ MyObj. Nic dziwnego, że nie możesz zadzwonić do swojego konstruktora. Zobacz dla dobrego wyjaśnienia.

+0

Aby rozwinąć - to tylko problem w niektórych kontekstach. Napisz "throw myexceptionclass();", na przykład, i nie ma zamieszania. Język jest niejednoznaczny w kontekście Petesa, ale ujednoznacznienie reguł (powód, dla którego język ściśle nie jest tak naprawdę niejednoznaczny) wybiera jedną interpretację. Oczywiście reguły ujednoznaczniające oznaczają, że język nie jest tak naprawdę niejednoznaczny - ale parsujący eksperci twierdzą, że tak jest, więc mam też prawo! Najczęstsze reguły ujednoznaczniające w wielu językach dotyczą priorytetów operatorów i ich asocjacji - C i C++ są znacznie bardziej niejednoznaczne, co powoduje pewne dziwne problemy. – Steve314

44

To się nazywa najbardziej irytujący problem z parsowaniem. Kiedy widzi parser

MyClass myObj(); 

on myśli, że są deklarowania funkcji o nazwie myObj że nie posiada żadnych parametrów i zwraca MyClass.

Aby uzyskać wokół niego, należy:

MyClass myObj; 
+0

Witam, oprócz przydzielenia odpowiednio na stos i stertę, czy istnieje jakaś różnica między 'MyClass obj' i' MyClass * obj = new MyClass() '? – SexyBeast

+1

Kilka. Pierwszy deklaruje obiekt "obj" jako obiekt typu 'MyClass' i zostanie automatycznie zwolniony po opuszczeniu zasięgu. Drugi deklaruje 'obj' jako obiekt typu' MyClass * ', który musi zostać ręcznie zwolniony i będzie dostępny po zakończeniu zasięgu. –

+0

Tak, tak, to jest dokładnie wynikiem przydzielenia na stos i stos, odpowiednio? – SexyBeast

4
MyClass myObj(); 

To jest analizowany jako deklaracji funkcji, funkcja nazywa myObj, przyjmuje żadnych argumentów i zwraca myClass obiekt. Nigdy nie widziałem, żeby kompilator to akceptował. Z drugiej strony, MyClass* myPtr = new MyClass(); jest do przyjęcia, może być tak, że jesteś zdezorientowany?

18

Znalazłem to w standardzie C++ (§8.5.8):

An object whose initializer is an empty set of parentheses, i.e.,(), shall be value-initialized.

[Note: since() is not permitted by the syntax for initializer,

X a(); 

is not the declaration of an object of class X, but the declaration of a function taking no argument and returning an X. The form () is permitted in certain other initialization contexts (5.3.4, 5.2.3, 12.6.2). —end note ]

Powiązane problemy