为什么使用前向声明而不是 #include 时会出现不完整的类型

Why do I get incomplete type when using forward declaration instead of #include?

本文关键字:类型 声明 为什么 #include      更新时间:2023-10-16

这里有state_machine.h:

#ifndef STATE_MACHINE_H
#define STATE_MACHINE_H
// state machine classes
//#include "state_t.h"
class state_t;
class state_machine
{
public:
    state_machine();
    void change_state(state_t *newState);
    void process_state(int data);
private:
    state_t *_state;
};
#endif // STATE_MACHINE_H

这是state_t.h:

#ifndef STATE_T_H
#define STATE_T_H
#include <QByteArray>
#include <QDebug>
//#include "state_machine.h"
class state_machine;
class state_t
{
public:
    state_t(QByteArray stateName);
    virtual ~state_t();
    virtual void processState(state_machine *sm, int input) = 0;
    void defaultUnknownEventHandler(int event);
    QByteArray name;
};
#endif // STATE_T_H

然后一些状态类,它们或多或少都是一样的,我只列出一个:

测试状态1.h:

#ifndef TESTSTATE1_H
#define TESTSTATE1_H
#include "state_t.h"
class testState1 : public state_t
{
public:
    testState1();
    void processState(state_machine *sm, int event);
};
#endif // TESTSTATE1_H

测试状态.cpp:

#include "teststate1.h"
#include "teststate2.h"
testState1::testState1() :
    state_t("state1")
{
}
void testState1::processState(state_machine *sm, int event)
{
    qDebug() << name << ": event" << event;
    switch (event)
    {
        case 2:
        {
            // error: invalid use of incomplete type 'class state_machine'
            sm->change_state(new testState2()); 
            break;
        }
        default:
        {
            defaultUnknownEventHandler(event);
            break;
        }
    }
}

问题:

我正在尝试整理我的代码,并使用前向声明使用最少量的标头包含(尤其是在头文件中)。您可以在state_machine类标头中看到我已经注释掉了#include "state_t.h"并将其替换为前向声明class state_t;。这有效,我的代码编译并运行。

然后,在 state.h 中,我用前向声明class state_machine;替换了#include "state_machine.h"(你可以看到我在哪里注释掉了它)。

但是现在我得到了错误error: invalid use of incomplete type 'class state_machine'我在testState1.cpp代码中注释了该错误。但我不知道为什么。为什么state_machine是不完整的类型?

teststate.cpp需要state_machine的定义;所以包括state_machine.h

"不完整"意味着编译器只看到了一个声明,class state_machine;,而不是一个完整的定义。可以使用不完整的类型执行各种操作,例如声明指针或引用。但是你不能调用成员函数(就像你在这里所做的那样),或者更一般地做任何需要了解类成员的事情,没有完整的定义。