使用变量而不引起循环依赖

Using a variable without causing circular dependancy

本文关键字:循环 依赖 变量      更新时间:2023-10-16

我有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*)

Game是我的应用程序的主体。它的头文件包括Child1和Child2,并使用这些类型初始化变量。它声明了类"Game"

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();
};

我希望能够在Parent, Child1Child2中使用Game中包含的数据。

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

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

Main.h

#pragma once
#include "Game.h"
Game myGame;

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

有什么办法我可以:

  1. 在"Main.h"中声明一个未初始化的Game类型的myGame
  2. 用"Main.cpp"中收集的信息初始化myGame
  3. 在Parent, Child1和Child2中使用myGame,而不引起循环依赖,包括在其中声明myGame的文件。

我是否能够在"Main.h"中使用#include "Game.h"来创建一个游戏变量,但防止包含继承到包含"Main.h"的文件?

前向声明允许引用未定义的对象,但是没有定义就不能实例化它们。上面写着"我以后再告诉你"。

非法:

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;
}

你在头文件中承诺编译器的"later"是源文件。

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,或者在它上面调用函数。