2010-02-23 12 views
44

Ich kompilierte ein C++ - Programm in Cygwin mit g ++ und ich hatte eine Klasse, deren Konstruktor keine Argumente hatte. Ich hatte die Zeilen:Sind für einen Konstruktor ohne Argumente keine Sprachklammern ein Sprachstandard?

MyClass myObj(); 
myObj.function1(); 

Und wenn es zu kompilieren versuchen, bekam ich die Nachricht:

Fehler: Antrag auf Mitglieder function1 'in ‚myObj‘, die von nicht-Klasse Typ ‚MyClass()() '

Nach ein wenig Forschung, fand ich, dass die Lösung war, diese erste Zeile zu ändern MyClass myObj;

Ich könnte schwören, ich habe leere Konstruktor Deklarationen mit Klammern in C++ vor getan. Ist das wahrscheinlich eine Einschränkung des Compilers, den ich verwende, oder sagt der Sprachstandard wirklich, dass keine Klammern für einen Konstruktor ohne Argumente verwendet werden?

Antwort

49

Obwohl MyClass myObj(); als Objektdefinition mit einem leeren Initialisierer oder einer Funktionsdeklaration analysiert werden kann, gibt der Sprachstandard an, dass die Mehrdeutigkeit immer zugunsten der Funktionsdeklaration aufgelöst wird. Ein leerer Klammerninitialisierer ist in anderen Zusammenhängen z.B. in einem new Ausdruck oder Konstruieren einer Wert initialisierten temporär.

1

Der Standard erfordert keine Klammern.

int* x = new int; 

ist rechtliche Syntax.

In Ihrem Fall ist myclass myobj(); ein Funktionsprototyp. Wobei myclass myobj; eine Variable ist.

3

Ihre Zeile lässt den Compiler denken, dass Sie eine Funktion mit dem Namen myObj deklarieren, die keine Argumente akzeptiert und eine MyClass zurückgibt. Diese Mehrdeutigkeitsauflösung ist in der Tat ärgerlich.

10

Dies ist ein ziemlich bekanntes Problem und ist nicht vom Compiler abhängig. Im Wesentlichen haben Sie eine Funktion deklariert, die den Typ MyObj zurückgibt. Es ist nicht überraschend, dass Sie den Konstruktor nicht aufrufen konnten. Eine gute Erklärung finden Sie in der C++ faq lite

+0

Um zu erweitern - es ist nur ein Problem in bestimmten Kontexten. Schreiben Sie zum Beispiel "throw myexceptionclass();" und es gibt keine Verwirrung. Die Sprache ist im Petes-Kontext mehrdeutig, aber die Disambiguierungsregeln (der Grund, warum die Sprache streng genommen nicht wirklich mehrdeutig ist) wählen eine Interpretation aus. Natürlich bedeuten die Regeln der Disambiguierung, dass die Sprache nicht wirklich zweideutig ist - aber Parsing-Experten sagen es trotzdem, also darf ich auch! Die häufigsten Disambiguierungsregeln in vielen Sprachen sind Operatorenpräzedenz und Assoziativität. C und C++ sind vieldeutiger und es gibt einige seltsame Probleme. – Steve314

44

Dies wird als das ärgerlichste Parse-Problem bezeichnet. Wenn der Parser

MyClass myObj(); 

sieht es denkt, dass Sie eine Funktion namens deklarieren myObj, die keine Parameter hat und gibt einen MyClass.

um es zu bekommen, verwenden:

MyClass myObj; 
+0

Hallo, gibt es, abgesehen von Stack und Heap, einen Unterschied zwischen 'MyClass obj' und' MyClass * obj = new MyClass() '? – SexyBeast

+1

Ein paar. Der erste deklariert "obj" als Objekt vom Typ 'MyClass' und wird automatisch freigegeben, wenn der Bereich beendet wird. Der zweite deklariert 'obj' als Objekt vom Typ' MyClass * ', das manuell freigegeben werden muss und nach dem Beenden des Bereichs verfügbar sein wird. –

+0

Ja, ja, das ist genau das Ergebnis der Zuweisung auf dem Stack bzw. dem Heap, richtig? – SexyBeast

4
MyClass myObj(); 

, die als Funktionsdeklaration analysiert ist, wird die Funktion myObj genannt, hat keine Argumente und Objekt MyClass kehrt zurück. Ich habe noch nie einen Compiler gesehen, der das akzeptiert. Auf der anderen Seite MyClass* myPtr = new MyClass(); ist akzeptabel, kann das dich verwirrt haben?

18

Ich fand dies in der C++ - Standard (§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 ]

Verwandte Themen