c++ vererbung Sind bei einem Konstruktor ohne Argumente keine Sprachklammern?




c++ vererbung konstruktor reihenfolge (7)

Ich kompilierte ein C ++ - Programm in Cygwin mit g ++ und ich hatte eine Klasse, deren Konstruktor keine Argumente hatte. Ich hatte die Zeilen:

MyClass myObj();
myObj.function1();

Und als ich versuchte, es zu kompilieren, bekam ich die Nachricht:

error: request for member 'function1' in 'myObj', which is of non-class type 'MyClass ()()'

Nach ein wenig Nachforschungen fand ich, dass die Lösung darin bestand, diese erste Zeile zu ändern

MyClass myObj;

Ich könnte schwören, dass ich leere Konstruktordeklarationen mit Klammern in C ++ vorher getan habe. 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?



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

MyClass myObj();

Sie denkt, dass Sie eine Funktion namens myObj , die keine Parameter enthält und eine MyClass zurückgibt.

Um es zu umgehen, verwenden Sie:

MyClass myObj;

Obwohl MyClass myObj(); könnte als Objektdefinition mit einem leeren Initialisierer oder einer Funktionsdeklaration geparst werden. Der Sprachstandard gibt an, dass die Mehrdeutigkeit immer zugunsten der Funktionsdeklaration aufgelöst wird. Ein leerer Klammerninitialisierer ist in anderen Kontexten zulässig, z. B. in einem new Ausdruck oder beim Konstruieren eines temporär initialisierten Wertes .


Ich habe dies im C ++ - Standard (§8.5.8) gefunden:

Ein Objekt, dessen Initialisierer ein leerer Satz von Klammern ist, dh, (), wird mit Wert initialisiert.

[Hinweis: da () nicht von der Syntax für den Initialisierer erlaubt ist,

X a ();

ist nicht die Deklaration eines Objekts der Klasse X, sondern die Deklaration einer Funktion, die kein Argument annimmt und ein X zurückgibt. Das form () ist in bestimmten anderen Initialisierungskontexten erlaubt (5.3.4, 5.2.3, 12.6.2). Endnote]


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 C ++ faq lite


Ihre Zeile myObj , dass der Compiler denkt, dass Sie eine Funktion namens myObj die keine Argumente annimmt und eine MyClass zurückgibt. Diese Mehrdeutigkeitsauflösung ist in der Tat ärgerlich.


Der Standard benötigt keine Klammern.

int* x = new int;

ist legale Syntax.

In deinem Fall myclass myobj(); ist ein Funktionsprototyp. Während myclass myobj; ist eine Variable.





standards