Ich habe zwei Klassen wie folgt deklariert:
class User
{
public:
MyMessageBox dataMsgBox;
};
class MyMessageBox
{
public:
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message> *dataMessageList;
};
Wenn ich versuche, es mit gcc zu kompilieren, wird der folgende Fehler ausgegeben:
MyMessageBox benennt keinen Typ
g++
und nichtgcc
Antworten:
Wann der Compiler die Klasse kompiliert
User
und zurMyMessageBox
Zeile gelangt ,MyMessageBox
wurde noch nicht definiert. Der Compiler hat keine AhnungMyMessageBox
, kann also die Bedeutung Ihres Klassenmitglieds nicht verstehen.Sie müssen sicherstellen, dass
MyMessageBox
es definiert ist, bevor Sie es als Mitglied verwenden. Dies wird durch Umkehren der Definitionsreihenfolge gelöst. Sie haben jedoch eine zyklische Abhängigkeit: Wenn Sie nachMyMessageBox
oben gehenUser
, wird in der Definition desMyMessageBox
NamensUser
nicht definiert!Was Sie tun können, ist vorwärts zu deklarieren
User
; das heißt, deklarieren Sie es, aber definieren Sie es nicht. Während der Kompilierung wird ein deklarierter, aber nicht definierter Typ als unvollständiger Typ bezeichnet . Betrachten Sie das einfachere Beispiel:Durch die nach vorne erklärt
User
,MyMessageBox
kann immer noch einen Zeiger oder Verweis auf sie bilden:Sie können dies nicht umgekehrt tun: Wie bereits erwähnt, muss ein Klassenmitglied eine Definition haben. (Der Grund dafür ist, dass der Compiler wissen muss, wie viel Speicher belegt
User
wird, und dass er die Größe seiner Mitglieder kennen muss.) Wenn Sie sagen würden:Es würde nicht funktionieren, da es die Größe noch nicht kennt.
Nebenbei bemerkt, diese Funktion:
Wahrscheinlich sollte keiner von beiden per Zeiger genommen werden. Sie können keine Nachricht ohne Nachricht senden, noch können Sie eine Nachricht ohne einen Benutzer senden, an den Sie sie senden können. Und beide Situationen können ausgedrückt werden, indem null als Argument an einen der Parameter übergeben wird (null ist ein vollkommen gültiger Zeigerwert!).
Verwenden Sie stattdessen eine Referenz (möglicherweise const):
quelle
MyMessageBox
wäre genug gewesen. Was wäre, wennMyMessageBox
es auch eine Variable vom TypUser
hätte - wäre das ein Deadlock?User
hätteMessageBox
eineUser
, die eine hätte, die eineMessageBox
hätte, die eineUser
hätte, die eineMessageBox
hätte, die eineUser
hätte, die eineMessageBox
hätteUser
...quelle
C ++ - Compiler verarbeiten ihre Eingaben einmal. Jede Klasse, die Sie verwenden, muss zuerst definiert worden sein. Sie verwenden,
MyMessageBox
bevor Sie es definieren. In diesem Fall können Sie einfach die beiden Klassendefinitionen austauschen.quelle
MyMessageBox
derUser
Typ in der Methodendeklaration.User
. Wichtiger Unterschied, da dies bedeutet, dass die Klasse Benutzer nur an diesem Punkt deklariert und nicht definiert werden muss . Aber siehe GMans umfangreichen Beitrag.User
Typ noch nicht deklariert ist.Sie müssen MyMessageBox vor dem Benutzer definieren, da der Benutzer das Objekt von MyMessageBox nach Wert einschließt (und der Compiler daher seine Größe kennen sollte).
Außerdem müssen Sie den Benutzer vor MyMessageBox deklarieren, da MyMessageBox ein Mitglied vom Typ Benutzer * enthält.
quelle
In einem ähnlichen Zusammenhang, wenn Sie hatten:
Dann würde das auch funktionieren, da der Benutzer in MyMessageBox als Zeiger definiert ist
quelle
Sie müssen den Prototyp deklarieren, bevor Sie ihn verwenden:
Bearbeiten : Die Typen wurden ausgetauscht
quelle
In C ++ wird immer empfohlen, dass Sie eine Klasse pro Header-Datei haben. Siehe diese Diskussion in SO [ 1 ]. Die Antwort von GManNickG erklärt, warum dies passiert. Der beste Weg, dies zu lösen, besteht darin, die
User
Klasse in eine Header-Datei (User.h
) und dieMyMessageBox
Klasse in eine andere Header-Datei (MyMessageBox.h
) zu setzen. Dann in IhremUser.h
Sie umfassenMyMessageBox.h
und inMyMessageBox.h
Ihnen enthaltenUser.h
. Vergessen Sie nicht "include gaurds" [ 2 ], damit Ihr Code erfolgreich kompiliert wird.quelle