windows C++中的“X不命名类型”错误

sq1bmfud  于 2022-12-14  发布在  Windows
关注(0)|答案(8)|浏览(145)

我有两个类声明如下:

class User
{
public:
  MyMessageBox dataMsgBox;
};

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

当我尝试使用gcc编译它时,它给出了以下错误:
MyMessageBox不命名类型

r6l8ljro

r6l8ljro1#

当编译器编译类User并到达MyMessageBox行时,MyMessageBox尚未定义。编译器不知道MyMessageBox存在,因此无法理解类成员的含义。
您需要确保在将MyMessageBox用作成员 * 之前 * 定义了它。这可以通过颠倒定义顺序来解决。但是,您有一个循环依赖关系:如果您将MyMessageBox移动到User之上,则在MyMessageBox的定义中,将不会定义名称User
你能做的就是 * 向前声明 * User;也就是说,声明它但不定义它。在编译过程中,一个被声明但没有定义的类型被称为 * 不完整类型 *。考虑一个更简单的例子:

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

通过前向声明UserMyMessageBox仍然可以形成指向它的指针或引用:

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

您 * 不能 * 用相反的方式来执行此操作:如前所述,类成员需要有一个定义。(原因是编译器需要知道User占用了多少内存,并且需要知道其成员的大小。)如果您说:

class MyMessageBox;

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

它不会工作,因为它还不知道大小。
顺便说一句,该函数:

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

可能不应该用指针来处理这两种情况。没有消息就不能发送消息,没有用户就不能发送消息。这两种情况都可以通过传递null作为参数来表示(null是一个完全有效的指针值!)
而是使用指涉(可能是const):

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

r8xiu3jd2#

1.向前声明用户
1.将MyMessageBox的声明放在User之前

pnwntuvh

pnwntuvh3#

C++编译器只处理一次输入。你使用的每个类都必须先被定义。在定义它之前,你使用MyMessageBox。在这种情况下,你可以简单地交换两个类的定义。

ctzwtxfj

ctzwtxfj4#

您需要在User之前定义MyMessageBox--因为User通过value* 包含MyMessageBox * 的对象(因此编译器应该知道它的大小)。
此外,您还需要在MyMessageBox之前 * 向前声明 * User--因为MyMessageBox包含User* 类型的成员。

wkftcu5l

wkftcu5l5#

与此相关,如果您有:

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

这样也可以,因为User在MyMessageBox中定义为指针

vwkv1x7d

vwkv1x7d6#

您必须在使用它之前宣告原型:

class User;

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

class User
{
public:
 MyMessageBox dataMsgBox;
};

edit:交换类型

erhoui1w

erhoui1w7#

在C++中总是鼓励每个头文件都有一个类,我在SO [ 1 ]. GManNickG中看到了这个讨论,答案告诉我们为什么会发生这种情况。但是解决这个问题的最好方法是将User类放在一个头文件中(User.h)和MyMessageBox类在另一个头文件中(MyMessageBox.h)。然后在User.h中包含MyMessageBox.h,在MyMessageBox.h中包含User.h。不要忘记“包含保护”[ 2 ]以便代码成功编译。

ldfqzlk8

ldfqzlk88#

在我的例子中,这个信息量很小的错误是由循环依赖引起的。

// A.hpp
#include "B.hpp"

class A {
    B b;
}

// B.hpp
#include "A.hpp"

class B {
    A a;
}

我将第二个文件更改为

// B.hpp
class A;

class B {
    A a;
}

...并且所有的编译器错误,以及我的IDE中突然缺少语法突出显示,都消失了。
我确实需要稍后在B.cpp文件的顶部放置一个#include "A.hpp",但这没关系,因为在这种情况下(B.cpp -> A.hpp -> B.hpp -> /)没有循环依赖。

相关问题