J'ai deux classes déclarées comme ci-dessous:
class User
{
public:
MyMessageBox dataMsgBox;
};
class MyMessageBox
{
public:
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message> *dataMessageList;
};
Lorsque j'essaie de le compiler en utilisant gcc, cela donne l'erreur suivante:
MyMessageBox ne nomme pas de type
g++
et nongcc
Réponses:
Lorsque le compilateur compile la classe
User
et accède à laMyMessageBox
ligne,MyMessageBox
n'a pas encore été défini. Le compilateur n'a aucune idée de l'MyMessageBox
existence et ne peut donc pas comprendre la signification de votre membre de classe.Vous devez vous assurer qu'il
MyMessageBox
est défini avant de l' utiliser en tant que membre. Ceci est résolu en inversant l'ordre des définitions. Cependant, vous avez une dépendance cyclique: si vous vous déplacezMyMessageBox
ciUser
- dessus , la définition duMyMessageBox
nomUser
ne sera pas définie!Ce que vous pouvez faire, c'est déclarer en avant
User
; autrement dit, déclarez-le mais ne le définissez pas. Lors de la compilation, un type déclaré mais non défini est appelé type incomplet . Prenons l'exemple le plus simple:En déclarant en avant
User
,MyMessageBox
peut toujours former un pointeur ou une référence à celui-ci:Vous ne pouvez pas faire cela dans l'autre sens: comme mentionné, un membre de la classe doit avoir une définition. (La raison est que le compilateur a besoin de savoir combien de mémoire
User
prend et de savoir qu'il a besoin de connaître la taille de ses membres.) Si vous deviez dire:Cela ne fonctionnerait pas, car il ne connaît pas encore la taille.
En passant, cette fonction:
Ne devrait probablement pas prendre l'un ou l'autre de ces points par pointeur. Vous ne pouvez pas envoyer un message sans message, ni envoyer un message sans un utilisateur à qui l'envoyer. Et ces deux situations sont exprimables en passant null comme argument à l'un ou l'autre des paramètres (null est une valeur de pointeur parfaitement valide!)
Utilisez plutôt une référence (éventuellement const):
la source
MyMessageBox
aurait suffi. Et siMyMessageBox
avait une variable de typeUser
aussi - serait-ce une impasse?User
aurait unMessageBox
qui aurait unUser
, qui aurait unMessageBox
qui aurait unUser
, qui aurait unMessageBox
qui aurait unUser
, qui aurait unMessageBox
qui aurait unUser
...la source
Les compilateurs C ++ traitent leur entrée une fois. Chaque classe que vous utilisez doit avoir été définie en premier. Vous utilisez
MyMessageBox
avant de le définir. Dans ce cas, vous pouvez simplement permuter les deux définitions de classe.la source
MyMessageBox
a leUser
type dans elle est la déclaration de la méthode.User
. Distinction importante, car cela signifie que la classe User ne doit être déclarée qu'à ce stade, non définie . Mais voyez le long article de GMan.User
type n'est pas encore déclaré.Vous devez définir MyMessageBox avant User - car l'utilisateur inclut l'objet de MyMessageBox par valeur (et le compilateur doit donc connaître sa taille).
Vous devrez également transmettre la déclaration de l' utilisateur avant MyMessageBox - car MyMessageBox inclut un membre de type User *.
la source
Sur une note connexe, si vous aviez:
Cela fonctionnerait également, car l'utilisateur est défini dans MyMessageBox en tant que pointeur
la source
Vous devez déclarer le prototype avant de l'utiliser:
edit : permuté les types
la source
Il est toujours recommandé en C ++ que vous ayez une classe par fichier d'en-tête, voir cette discussion dans SO [ 1 ]. La réponse de GManNickG explique pourquoi cela se produit. Mais la meilleure façon de résoudre ce problème est de mettre la
User
classe dans un fichier d'en-tête (User.h
) et laMyMessageBox
classe dans un autre fichier d'en-tête (MyMessageBox.h
). Alors dans votreUser.h
vous incluezMyMessageBox.h
et dansMyMessageBox.h
vous incluezUser.h
. N'oubliez pas "include gaurds" [ 2 ] pour que votre code se compile avec succès.la source