类声明的循环依赖关系

Circular dependency of class delclarations

本文关键字:依赖 关系 循环 声明      更新时间:2023-10-16

我有两个带有单独标题的类:class Rendererclass TextureTexture实例旨在管理驻留在Renderer内存池中的一些数据,因此Texture实例不能独立于Renderer实例而存在。要获取Texture实例的句柄,只需使用正确的文件名调用Renderer::loadTextureRenderer在其数据库中搜索具有匹配文件名Texture对象,如果未找到匹配项,则实例化新纹理。

//renderer.h
#include "texture.h"
class renderer
{
public:
    Texture* loadTexture(std::string fileName);
private:
    std::map<std::string, Texture*> textureDb;
};
//texture.h
class Texture
{
public:
    Texture(std::string imageFileName);
};

我突然想到,将class Texture构造函数设为私有,并将Texture * Renderer::loadTexture(std::string filename)声明为class Renderer的朋友是合乎逻辑的:

//renderer.h
#include "texture.h"
class renderer
{
public:
    Texture* loadTexture(std::string fileName);
private:
    std::map<std::string, Texture*> textureDb;
};
//texture.h
class texture;
#include "renderer.h"
class Texture
{
private:
    Texture(std::string imageFileName);
    Texture(const Texture &);
    friend Texture* loadTexture(std::string);
};

但是,只有在包含 renderer.h 之前始终包含 texture.h 时,这才会编译,因为class Texture要求已经定义class Renderer。防止这种情况的最佳方法是什么?两个文件中都存在包含保护,但为简洁起见,此处省略了。

首先,从上面的代码中,尽可能向前声明。这应该会有所帮助。

// Renderer.h
class Texture;
class Renderer {
   ...
};
// Renderer.cpp
#include "Renderer.h"
#include "Texture.h"
...
// Texture.h
//class Renderer; // looks like this isn't needed
class Texture {
   ...
};
// Texture.cpp
#include "Renderer.h"
#include "Texture.h"
...

使用前向声明,您应该有足够的时间来声明指向 Render er 类标头中的 Texture 指针。看起来这就是您此时所需要的;将其余部分推送到渲染器.cpp。

接下来,避开朋友;但是,在这种情况下可能是可以接受的。

最后,循环依赖从来都不是一件好事。看看你是否可以稍微改变一下你的设计。看看是否可以引入接口或抽象基类来打破循环依赖关系。看起来渲染器根本不需要依赖纹理。

相反,考虑重写渲染器以依赖于某种 ITexture 接口,然后让 Texture 实现 ITexture:

class ITexture
{
   // no data members
   // no method bodies
   // only pure virtual method declarations
};
class Renderer
{
public:
    ITexture* loadTexture(std::string fileName);
private:
    std::map<std::string, ITexture*> textureDb;
};
class Texture : public ITexture
{
   ...
};