X noemt geen typefout in C++

Ik heb twee klassen zoals hieronder aangegeven:

class User
{
public:
  MyMessageBox dataMsgBox;
};
class MyMessageBox
{
public:
  void sendMessage(Message *msg, User *recvr);
  Message receiveMessage();
  vector<Message> *dataMessageList;
};

Als ik het probeer te compileren met gcc, geeft het de volgende foutmelding:

MyMessageBox noemt geen type


Antwoord 1, autoriteit 100%

Als de compiler de klasse User compileert en bij de regel MyMessageBox komt, is MyMessageBox nog niet gedefinieerd. De compiler heeft geen idee dat MyMessageBox bestaat, dus kan de betekenis van je klaslid niet begrijpen.

Je moet ervoor zorgen dat MyMessageBox is gedefinieerd voordat je het als lid gebruikt. Dit wordt opgelost door de definitievolgorde om te draaien. U hebt echter een cyclische afhankelijkheid: als u MyMessageBox boven User plaatst, dan in de definitie van MyMessageBox de naam User wordt niet gedefinieerd!

Wat u kunt doen is doorsturen declareren User; dat wil zeggen, definieer het maar definieer het niet. Tijdens het compileren wordt een type dat is gedeclareerd maar niet gedefinieerd een onvolledig type genoemd.
Overweeg het eenvoudigere voorbeeld:

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;
}

Door User door te geven, kan MyMessageBox nog steeds een pointer of verwijzing ernaar vormen:

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;
};

Je kunt niet dit andersom doen: zoals gezegd moet een klaslid een definitie hebben. (De reden is dat de compiler moet weten hoeveel geheugen User in beslag neemt, en om te weten hoe groot de leden zijn.) Als je zou zeggen:

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

Het zou niet werken, omdat het de maat nog niet weet.


Een kanttekening, deze functie:

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

Waarschijnlijk zou je geen van beide met de aanwijzer moeten nemen. U kunt geen bericht verzenden zonder bericht, en u kunt ook geen bericht verzenden zonder een gebruiker naar wie u het kunt sturen. En beide situaties kunnen worden uitgedrukt door null als argument door te geven aan een van beide parameters (null is een perfect geldige pointerwaarde!)

Gebruik liever een referentie (mogelijk const):

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

Antwoord 2, autoriteit 4%

  1. Gebruiker doorsturen
  2. Zet de verklaring van MyMessageBox voor Gebruiker

Antwoord 3, autoriteit 2%

C++-compilers verwerken hun invoer één keer. Elke klasse die u gebruikt, moet eerst zijn gedefinieerd. U gebruikt MyMessageBox voordat u het definieert. In dit geval kunt u eenvoudig de twee klassendefinities omwisselen.


Antwoord 4

U moet MyMessageBox definiëren vóór Gebruiker — omdat Gebruiker het object van MyMessageBox op waarde opneemt (en de compiler zou dus de grootte ervan moeten weten).

U moet ook de gebruiker doorsturen voor MyMessageBox — omdat MyMessageBox een lid van het type Gebruiker* bevat.


Antwoord 5

Over een verwante opmerking, als u het volgende had:

    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;
    };

Dan zou dat ook werken, omdat de Gebruiker in MyMessageBox als een pointer is gedefinieerd


Antwoord 6

U moet het prototype declareren voordat u het gebruikt:

class User;
class MyMessageBox
{
public:
 void sendMessage(Message *msg, User *recvr);
 Message receiveMessage();
 vector<Message> *dataMessageList;
};
class User
{
public:
 MyMessageBox dataMsgBox;
};

bewerken: de typen verwisseld


Antwoord 7

Het wordt altijd aangemoedigd in C++ dat je één klasse per headerbestand hebt, zie deze discussie in SO [1].
Het antwoord van GManNickG vertelt waarom dit gebeurt. Maar de beste manier om dit op te lossen, is door de klasse User in het ene headerbestand (User.h) en de klasse MyMessageBox in een ander headerbestand te plaatsen ( MyMessageBox.h). Vervolgens neemt u in uw User.h MyMessageBox.h op en in MyMessageBox.h neemt u User.h op. Vergeet “include gaurds” [2] niet, zodat uw code succesvol wordt gecompileerd.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Other episodes