为什么我需要转发声明类foo而不是class bar,即使'foo.h'和'bar.h'都包括在内?

Qua*_*ity 2 c++ forward-declaration

尝试编译此代码时出现C2143错误; 我通过前向声明来修复它class Level,但我很困惑为什么需要这个,因为我已经包含了#include Level.h,这当然Level是定义的.什么混淆了我更多,不过,是我似乎需要采取同样的措施,在同一个地方类似的声明.这是我的代码:

// global.h
// Global variables

#pragma once

#include "Level.h"
#include "view.h"
#include "ActorPlayer.h"

class Level; // Without this line C2143 (missing ; before *) is
             // generated after 'extern Level'

extern Level* gamelevel;
extern View* view;
extern bool gameover;
extern bool player_turn;
extern int game_ticks;
extern ActorPlayer* act_player;
Run Code Online (Sandbox Code Playgroud)

我的问题是,为什么我不需要一个class View;和一个class ActorPlayer;?有什么相关的区别?

如果重要,这里是Level.h:

// Level.h
// Header file for Level class

#pragma once
#include "Terrain.h"
#include "global.h"
#include "hex_math.h"

class Level
{
public:
    const int WIDTH;
    const int HEIGHT;

    Level();
    Level(int width, int height);
    Level(int radius);
    ~Level();

    bool isInBounds(OrdPair coord);

    int terrainAt(OrdPair coord);

    void update();

private:
    int** terrain;

    void init();

    void fillHex(int qCenter, int rCenter, int radius, int terrainID);

};
Run Code Online (Sandbox Code Playgroud)

650*_*502 7

问题是你与包含文件有一个循环依赖:

global.h includes level.h
level.h includes global.h
Run Code Online (Sandbox Code Playgroud)

会发生什么

  1. 编译器开始阅读 level.h
  2. 读取pragma once标记已包含的文件
  3. 查找包含global.h并开始阅读(此时)
  4. 读取pragma once标记已包含的文件
  5. 找到包含level.h但忽略它(它被标记为2)
  6. 继续阅读其余部分,global.h但课程Level未知

如果项目不是微不足道的,那么你应该制作一个类和模块的图表,并决定什么依赖于(建立在什么).该图应该是DAG(没有循环).更具体地说,应该可以将模块细分为"层",其中来自较低层的模块不依赖于较高层中的模块.

如果你的依赖关系图中有一个循环,项目将更难处理(例如单元测试),因为你的模块不是真正的模块,但整个程序只是一个巨大的代码球.