繁体   English   中英

C++ 中的“X 没有命名类型”错误

[英]"X does not name a type" error in C++

我有两个类声明如下:

class User
{
public:
  MyMessageBox dataMsgBox;
};

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

当我尝试使用 gcc 编译它时,出现以下错误:

MyMessageBox 没有命名类型

当编译器编译类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);
  1. 转发声明用户
  2. 将MyMessageBox的声明放在User之前

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

您需要在User之前定义MyMessageBox - 因为User 按值包含MyMessageBox 对象(因此编译器应该知道它的大小)。

此外,您还需要转发声明 User befor MyMessageBox - 因为MyMessageBox包含User *类型的成员。

在相关的说明中,如果您有:

    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中被定义为指针

您必须在使用之前声明原型:

class User;

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

class User
{
public:
 MyMessageBox dataMsgBox;
};

编辑 :交换类型

在C ++中总是鼓励每个头文件有一个类,请参阅SO [ 1 ]中的这个讨论。 GManNickG回答说明了为什么会发生这种情况。 但解决此问题的最佳方法是将User类放在一个头文件( User.h )中,将MyMessageBox类放在另一个头文件( MyMessageBox.h )中。 然后在您的User.h包含MyMessageBox.h ,在MyMessageBox.h包含User.h 不要忘记“包括gaurds”[ 2 ],以便您的代码成功编译。

在我的例子中,事实证明这个非常无意义的错误是由循环依赖引起的。 代替

// 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 -> / )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM