前向声明覆盖完整定义

Forward declaration overriding full definition

我知道有一些题目是前向声明的,但是看了之后好像不太符合这种情况。我通常明白发生了什么,需要一个完整的定义来分配。但是,我真的认为我在这里有一个完整的定义,所以我很困惑。

//game.h
#include "wizard.h"
#include "warrior.h"
#include "archer.h"

#include "fighter.h"

#ifndef GAME_H
#define GAME_H

enum movetype{
    BOOST,
    ATTACK,
    SPECIAL,
    SHIELD
};

struct move{
    enum movetype type;
    fighter * source;
    fighter * target;
};

class game{
public:
    game();
    ~game();
    void execmove(move&);
    bool trymove();

private:
    bool turn;
    fighter*  t1 [3];
    fighter*  t2 [3];
};

#endif

所以在游戏中我包括所有其他 类 在fighter中我转发宣告warrior:

//fighter.h
#ifndef FIGHTER_H
#define FIGHTER_H

class fighter;
class warrior;

struct link {
    fighter * warrior;
    fighter * target;
};

class fighter{
private:


public:
    fighter();
    virtual ~fighter();
    void action(int, fighter*);
    virtual void special(fighter*);
    void attack(fighter*);
    void defend();
    void tick();
    void damage(int,int);
    void createLink(warrior *);
    void removeLink();
protected:
    int hp;
    int priority;
    int boosts;
    int shields;
    bool alive;
    struct link l;
};




#endif

但是当我尝试在游戏中分配战士时:

//game.cpp
#include <iostream>
#include "game.h"


game::game()
{
    t1[0] = new warrior();
    t1[1] = new wizard();
    t1[2] = new archer();

    t2[0] = new warrior();
    t2[2] = new archer();
    t2[1] = new wizard();



}

game::~game()
{
    for(int i = 0; i<3; i++)
    {
        delete t1[i];
        delete t2[i];
    }
}


void game::execmove(move& m)
{

}

我得到:

game.cpp:9:14: error: allocation of incomplete type 'warrior'
        t1[0] = new warrior();
                    ^~~~~~~
./fighter.h:7:7: note: forward declaration of 'warrior'
class warrior;
      ^
game.cpp:13:14: error: allocation of incomplete type 'warrior'
        t2[0] = new warrior();
                    ^~~~~~~
./fighter.h:7:7: note: forward declaration of 'warrior'
class warrior;

似乎我前向声明的事实让编译器忽略了我还包括了完整定义的事实,这真的很奇怪。我想知道是否缺少某些东西,因为如果前向声明使完整定义被忽略,我不知道如何修复它。

底线:既然我在 game.h 中包含了完整的 warrior.h 文件,为什么我不能分配 warrior?

这里是warrior.h:

#include "fighter.h"

#ifndef FIGHTER_H
#define FIGHTER_H

class warrior{
public:
    warrior();
    ~warrior();
    void special(fighter);
private:


};

#endif

将 warrior.h 更改为:(即正确包含守卫)

#ifndef WARRIOR_H
#define WARRIOR_H

#include "fighter.h"

class warrior{
public:
    warrior();
    ~warrior();
    void special(fighter);
private:


};

#endif

如果支持,最好还是使用 #pragma once

错误命名的守卫导致它不包括 warrior 文件。谢谢@1201ProgramAlarm

不同的.h文件需要使用不同的include guard符号。

"fighter.h" 定义 FIGHTER_H,因此当在 "warrior.h" 中遇到 #if 检查时,将跳过 class warrior 的定义。