c ++: erwarteter Klassenname vor '{' token

8

Wenn ich versuche, diesen Code auszuführen:

Lehrer.cpp:

%Vor%

Lehrer.h:

%Vor%

Person.h:

%Vor%

Ich erhalte diese Fehler:

%Vor%

Alle drei dieser Fehler verwirren mich. Wenn die Instructor-Klasse von Person abgeleitet wurde und innerhalb von Person das Gender-Feld geschützt ist, warum erhalte ich error: ‘gender’ was not declared in this scope sowie error: cannot call member function ‘virtual void Person::print()’ without object ?

Ich habe das Gefühl, dass ich hier offensichtlich etwas falsch mache, wie zum Beispiel das falsche Einbinden der Dateien oder ähnliches. Jede Hilfe wird geschätzt.

    
user2628156 07.05.2014, 02:02
quelle

5 Antworten

8

Sie müssen person.h in instructor.h einfügen, andernfalls ist das Token Person dem Compiler unbekannt. Und wenn Sie dies tun, stellen Sie sicher, dass Sie person.h von instructor.cpp entfernen. Andernfalls erhalten Sie einen Re-Deklaration Fehler. Es ist jedoch üblich, #ifdef Direktiven in Header-Dateien zu verwenden, um Mehrfacheinschlüsse zu verhindern. wie in person.h

%Vor%

oder Sie können #pragma once in VC ++ verwenden.

Ein weiterer Fehler ist, dass Sie Person Anteil von Instructor nicht korrekt initialisieren. Im Konstruktor:

%Vor%

mach es so

%Vor%     
Rakib 07.05.2014 02:08
quelle
2

Mehrere Probleme:

  1. Zu der Zeit, als Sie Ihre Klasse Instructor definiert haben, ist Ihre Klasse Person noch nicht definiert. Du solltest #include "Person.h" am Anfang von Instructor.h haben, was zum zweiten Problem führt ...
  2. Ihre Header sind nicht gegen doppelte Includes geschützt (was der Fehler ist, den Sie in Ihrem obigen Kommentar sehen). Um dies zu beheben, benötigen Sie einen Include-Guard:

    %Vor%

    Beim zweiten Mal, wenn diese Datei enthalten ist, ist PERSON_H bereits definiert. Daher wird ignoriert, was zwischen #ifndef und #endif ist.

  3. Sie rufen den Basisklassenkonstruktor falsch auf. Die korrekte Syntax lautet:

    %Vor%

    Was Sie tun (indem Sie Person(n, d, g); in den Konstruktor schreiben) wird kompiliert, denn wenn Sie den Basisklassenkonstruktor nicht explizit aufrufen, versucht der Compiler, den parameterlosen Standardkonstruktor für Sie aufzurufen, und in Ihrem Fall Person hat zufällig einen Standardkonstruktor, der aufgerufen werden kann (wenn Person keinen Konstruktor hat, der keine Parameter akzeptiert, erhalten Sie einen Kompilierungsfehler). Die Auswirkung dieser Anweisung besteht jedoch einfach darin, ein temporäres Person -Objekt zu erstellen, das am Ende der Anweisung zerstört wird, und nicht den Basisklassenkonstruktor aufzurufen.

    Diese Syntax (eine sogenannte Member-Initialisierungsliste) kann auch verwendet werden, um andere Klassenmitglieder zu initialisieren, und tatsächlich ist dies der bevorzugte Weg:

    %Vor%
T.C. 07.05.2014 02:15
quelle
1

Jedes Mal, wenn der Compiler auf die Präprozessor-Direktive #include "FileName.h" stößt, versucht der Compiler, die enthaltene Klasse neu zu laden - und, wie ich glaube, neu zu definieren. Dies wird zu einem Fehler bei der Kompilierung führen. Sie können detaillierter über include guards oder den Wrapper #ifndef lesen, hier .

Um dagegen zu "wachen", verwenden wir include guards - , die vor Ihrem Code in Ihrer Header-Datei erscheinen müssen .

Zum Beispiel:

%Vor%

Das #ifndef steht für "falls nicht definiert". Der folgende Bezeichner - in allen Großbuchstaben für keinen anderen Grund als "so wird es gemacht" - wird per Konvention auch nach dem Klassennamen benannt (dies ermöglicht dem Compiler, eine Reihe von Dingen zu überprüfen, vor allem sicherzustellen, dass - wenn jeder der Konvention folgt) - dass keine andere Klasse mit demselben Namen in das Programm aufgenommen, referenziert oder definiert wurde.

Logischerweise kann man folgern, dass die nächsten zwei Wächter für "define" und "end falls undefined" stehen.

Wenn Sie Ihre #endif unmittelbar nach dem Schließen Ihrer Klassendeklaration einschließen, z. };#endif (siehe oben) dies wird auch zu einem Fehler bei der Kompilierung führen und einer, der vielleicht nicht sofort ersichtlich ist (obwohl ich denke, der Compiler ist ziemlich klar mit der daraus resultierenden Fehlermeldung).

Der andere Code, den ich einfüge, ist natürlich nur der Vertrautheit wegen und einer Demonstration dessen, was möglich ist.

    
Thomas 07.05.2014 02:23
quelle
0

Einige Dinge müssen behoben werden:

  1. Instructor.h muss #include "Person.h" haben. Es wird dort benötigt, damit Instructor versteht, von was es erbt. Dies muss nicht in Instructor.cpp enthalten sein, wenn Sie es in Instructor.h verschieben, da Instructor.cpp hat Instructor.h enthalten.
  2. Ich bin mir nicht sicher, ob Sie für Person eine abstrakte Basisklasse sein wollten, aber ich sehe keine Person.cpp oder irgendeine Implementierung von Elementfunktionen in Person.h . Auch wenn Person eine abstrakte Basisklasse sein soll, müssen Sie dem Konstruktor einen Funktionskörper geben, selbst wenn dieser leer ist.

    Person() {};

  3. Sie rufen Person::print in Instructor::print auf, ohne dass eine Implementierung vorhanden ist.

  4. Wenn Sie Vererbung verwenden, müssen Sie die Elementinitialisierungsliste verwenden, die den Basisklassenkonstruktor aufruft, um die Mitgliedsvariablen der Basisklasse zu initialisieren. In beiden Kursleiterkonstruktoren führt die Verwendung der Konstruktoren Person im Funktionskörper, wie Sie derzeit sind, nicht zum gewünschten Ergebnis.
    Außerdem ist die Verwendung von Initialisierungslisten effizienter und die akzeptierte Konvektion zum Setzen der eigenen Mitgliedsvariablen der Klasse.

    Instructor::Instructor() : Person(), salary(0) { }

    Instructor::Instructor(string n, string d, string g, int s) : Person(n, d, g), salary(s) { }

Fred Thomsen 07.05.2014 03:07
quelle
-1

Ist das nicht nur die Reihenfolge der Header-Dateien in der Instructor.cpp? Sie müssen zunächst Person.h und dann Instructor.h einbeziehen. Das ist es.

    
Ramana Babu 07.05.2014 03:10
quelle

Tags und Links