"X没有在C++中命名类型"错误

Rak*_*h K 117 c++ windows types

我有两个类声明如下:

class User
{
public:
  MyMessageBox dataMsgBox;
};

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

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

MyMessageBox没有命名类型

GMa*_*ckG 192

当编译器编译类User并到达该MyMessageBox行时,MyMessageBox尚未定义.编译器不知道MyMessageBox存在,因此无法理解您的类成员的含义.

将其用作成员之前,您需要确保MyMessageBox已定义.这可以通过颠倒定义顺序来解决.但是,你有一个循环依赖:如果你移动到上面,那么在名称的定义中将不会被定义!MyMessageBoxUserMyMessageBoxUser

你可以做的是向前宣布 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;
}
Run Code Online (Sandbox Code Playgroud)

通过前向声明User,MyMessageBox仍然可以形成指针或引用它:

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;
};
Run Code Online (Sandbox Code Playgroud)

不能反过来这样做:如上所述,类成员需要有一个定义.(原因是编译器需要知道User占用了多少内存,并且知道它需要知道其成员的大小.)如果你要说:

class MyMessageBox;

class User
{
public:
    // size not available! it's an incomplete type
    MyMessageBox dataMsgBox;
};
Run Code Online (Sandbox Code Playgroud)

它不起作用,因为它还不知道尺寸.


另外,这个功能:

 void sendMessage(Message *msg, User *recvr);
Run Code Online (Sandbox Code Playgroud)

可能不应该通过指针采取其中任何一个.您无法在没有消息的情况下发送消息,也无法在没有用户发送消息的情况下发送消息.并且这两种情况都可以通过将null作为参数传递给任一参数来表达(null是一个完全有效的指针值!)

相反,使用引用(可能是const):

 void sendMessage(const Message& msg, User& recvr);
Run Code Online (Sandbox Code Playgroud)

  • @Amargosh:是的,这是不可能的.逻辑上也不可能,因为`User`会有一个`MessageBox`,它有一个`User`,它有一个`MessageBox`,它有一个`User`,它有一个`MessageBox`,它有一个``用户`,它将有一个`MessageBox`,它有一个`User` ... (12认同)
  • +1 今天学到了一些东西 - 我认为提前声明`MyMessageBox`就足够了。如果`MyMessageBox` 也有一个`User` 类型的变量怎么办——这会是一个死锁吗? (4认同)

Bri*_*ndy 8

  1. 转发声明用户
  2. 将MyMessageBox的声明放在User之前


Mew*_*Mew 5

就我而言,事实证明这个非常无信息的错误是由循环依赖引起的。代替

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

class A {
    B b;
}

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

class B {
    A a;
}
Run Code Online (Sandbox Code Playgroud)

我将第二个文件更改为

// B.hpp
class A;

class B {
    A a;
}
Run Code Online (Sandbox Code Playgroud)

...所有的编译器错误,以及我的 IDE 中突然缺少语法突出显示的问题都消失了。

我确实需要稍后#include "A.hpp"在文件顶部放置 a B.cpp,但这很好,因为在这种情况下不存在循环依赖 ( B.cpp -> A.hpp -> B.hpp -> /)。