172 votes

ne nomme pas une erreur de type en C ++

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 un type". S'il vous plaît aidez-moi à cet égard.

253voto

GManNickG Points 155079

Lorsque le compilateur compile la classe User et arrive à l' MyMessageBox ligne, MyMessageBox n'a pas encore été défini. Il n'a aucune idée qu'il existe, ne peut pas comprendre le sens de votre membre de la classe.

Vous devez assurez - MyMessageBox est défini avant de l'utiliser comme un membre. Ce problème est résolu par l'inversion de la définition de l'ordre. Cependant, vous avez une dépendance cyclique: si vous déplacez MyMessageBox - dessus User, puis dans la définition de l' MyMessageBox nom User ne sera pas défini!

Ce que vous pouvez faire est de déclarer avant User, à déclarer, mais ne le définissent pas. Lors de la compilation, un type qui est déclarée mais non défini est appelé un type incomplète. Considérons l'exemple plus simple:

struct foo; // foo is *declared* to be a struct, but that struct is not yet defined

struct bar
{
    // this is okay, it's just a pointer;
    // we can point to something without knowing how that something is defined
    foo* fp; 

    // likewise, we can form a reference to it
    void some_func(foo& fr);

    // but this would be an error, as before, because it requires a definition
    /* foo fooMember; */
};

struct foo // okay, now define foo!
{
    int fooInt;
    double fooDouble;
};

void bar::some_func(foo& fr)
{
    // now that foo is defined, we can read that reference:
    fr.fooInt = 111605;
    fr.foDouble = 123.456;
}

Par l'avant de déclarer User, MyMessageBox peut encore former un pointeur ou une référence à ça:

class User; // let the compiler know such a class will be defined

class MyMessageBox
{
public:
    // this is ok, no definitions needed yet for User (or Message)
    void sendMessage(Message *msg, User *recvr); 

    Message receiveMessage();
    vector<Message>* dataMessageList;
};

class User
{
public:
    // also ok, since it's now defined
    MyMessageBox dataMsgBox;
};

Vous ne peut pas le faire dans l'autre sens: comme mentionné, un membre de la classe doit avoir une définition. (La raison en est que le compilateur a besoin de savoir combien de mémoire User , et de savoir qu'il a besoin de savoir la taille de ses membres.) Si vous dites:

class MyMessageBox;

class User
{
public:
    // size not available! it's an incomplete type
    MyMessageBox dataMsgBox;
};

Ça ne marcherait pas, car il ne sait pas la taille encore.


Sur une note de côté, cette fonction:

 void sendMessage(Message *msg, User *recvr);

Il est préférable de ne pas prendre l'une de ces par pointeur. Vous ne pouvez pas envoyer un message, sans un message, et vous ne pouvez envoyer un message à un utilisateur d'envoyer. Et ces deux situations sont exprimables en passant null comme un argument pour chaque paramètre (la valeur null est parfaitement valide la valeur du pointeur!)

Plutôt, utilisez une référence (éventuellement const):

 void sendMessage(const Message& msg, User& recvr);

12voto

Brian R. Bondy Points 141769
  1. Forward déclarer l'utilisateur
  2. Placez la déclaration de MyMessageBox avant l'utilisateur

4voto

MSalters Points 74024

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 échanger les deux définitions de classe.

3voto

Vous devez définir MyMessageBox avant User - car User inclut un objet de MyMessageBox en tant que valeur (le compilateur doit donc connaître sa taille).

En outre, vous devez transférer l' utilisateur déclaré avant MyMessageBox - car MyMessageBox inclut le membre de type User *.

3voto

awesomeamyg Points 11

Sur une note connexe, si vous aviez:

     class User; // let the compiler know such a class will be defined

    class MyMessageBox
    {
    public:
        User* myUser;
    };

    class User
    {
    public:
        // also ok, since it's now defined
        MyMessageBox dataMsgBox;
    };
 

Ensuite, cela fonctionnerait également, car l'utilisateur est défini dans MyMessageBox en tant que pointeur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X