使用变量而不会导致循环依赖

时间:2014-05-05 04:12:44

标签: c++ class inheritance include

我有5套“.h”& “.cpp”文件:

  • Main.cpp的
  • Game.h,Game.cpp
  • Parent.h,Parent.cpp
  • Child1.h,Child1.cpp
  • Child2.h,Child2.cpp

Main不包含类,也不包含头文件 - 并且是应用程序的起点。除此之外,它还使用收集的信息初始化“Game”类型的变量“myGame”。

Main.cpp的

#include "Game.h"
...
Game myGame(*parameters sent to constructor*)

游戏是我的应用程序的主体。它的标题包括Child1和Child2,并使用这些类型初始化变量。它声明了“游戏”类

Game.h

#pragma once

#include "Child1.h"
#include "Child2.h"

class Game
{
public:
    Game(HWND hWnd, ...);
    ~Game();

    Child1 child1Obj;
    Child2 child2obj[20];
    ...
private:
    ...
};

Parent概括了两个子类,并提供了类似的函数和变量。它的标题不包含其他文件。

Parent.h

#pragma once

class Parent
{
public:
    Parent(void);
    ~Parent(void);
    ...
};

Child1和Child2都相似,并包含父标题。

Child1.h

#pragma once
#include "Parent.h"

class Child1 :
    public Parent
{
public:
    Child1();
    ~Child1();
};

我希望能够使用GameParentChild1Child2中包含的数据。

我的第一个猜测是简单地将#include "Game.h"插入Parent.h的顶部,但这样做会导致循环依赖。

接下来,我想只要我想在myGame.中使用变量和函数,我就必须引用实际的游戏对象Main.cpp(在Game中创建)。但我不知道该怎么做。也许我可以提前在myGame文件中声明Main.h,如下所示:

Main.h

#pragma once
#include "Game.h"

Game myGame;

但是为了做到这一点,我仍然必须使用#include "Game.h",并在我想要使用myGame的文件顶部包含“Main.h” - 导致相同的如上所述的循环依赖问题。

我有什么办法可以:

  1. 在“Main.h”中声明未初始化的myGame类型游戏
  2. 使用“Main.cpp”
  3. 中收集的信息初始化myGame
  4. 通过包含声明myGame的文件,在Parent,Child1和Child2中使用myGame而不会导致循环依赖。
  5. 我是否可以在“Main.h”中使用#include "Game.h"来创建Game变量,但是阻止包含继承到包含“Main.h”的文件?

1 个答案:

答案 0 :(得分:2)

前向声明允许引用尚未定义的对象,但无法在没有定义的情况下对其进行实例化。它说"我稍后会告诉你#34;

非法:

class myGame;  // forward declaration, I'll tell you about this later
class myPlayer
{
public:
  myPlayer();
protected:
  myGame theGame;
}

法律:

class myGame;  // forward declaration, I'll tell you about this later
class myPlayer
{
public:
  myPlayer();
protected:
  myGame* theGame;
}

"后来",你在头文件中承诺编译器,是源文件。

myPlayer.cpp:

#inlcude "myPlayer.h"

// Tell the compiler what a myGame is, 
// other than something that can be pointed at
#inlcude "myGame.h" 

myPlayer::myPlayer() :
  theGame(new myGame())
{
}

自然地,真正的程序将变得更加复杂,具有构造函数的参数等。这个演示是关于类的结构,描述它们的文件以及它们的联锁关系。

前向声明的缺点是编译器没有获得有关正向声明的对象的信息,因此它无法生成一个 - 因此,它不能将一个放在另一个对象中。话虽如此,你可以指出一个,因为你已经说过有这样的东西,你有前进的声明,因此这些东西是合法的,用这些东西做事情是合法的就像拿走他们的记忆地址然后指向他们一样,或者引用他们的记忆地址。

当编译器深入到源文件(.cpp)时,您已经移交了前向声明对象的定义,现在它知道它们是什么以及可以用它们做什么。这就是你可以用指针或引用做事的地方,比如制作一个new,或者调用它上面的函数。