访问其他类上的变量的最佳方法

Best approach on accessing variables on other class

本文关键字:变量 方法 最佳 其他 访问      更新时间:2023-10-16

我现在正在为我们的引擎编写一个 Direct3D 渲染器。

问题是这样的:
在 OpenGL 中,我可以轻松地调用glClearColor()进行清除。
在 Direct3D 中,我需要使用 g_pd3dDevice 来调用ClearRenderTargetView()进行清除。

我们引擎的设计是这样的:

class Renderer
{
    // ...
}
class Direct3dWin32 : public Renderer
{
    private ID3D10Device* g_pd3dDevice;
}
class OpenGLWin32 : public Renderer
{
    // Nothing, I can call a function easily without relying on something
}

当我的ShaderManager类想要编译着色器时,问题就出现了。我需要使用Direct3dWin32类上的g_pd3dDevice

我的问题是,解决这个问题的最佳方法是什么?我正在考虑全局变量、单例类,或者只是在函数中传递类。

首先,我不禁注意到g_pd3dDevice,这不是全局的。它是指向设备 ID3D10Device* 的 COM 接口的类成员指针,它在这里不是全局的,也不应该是。

为了尽可能简单地回答您的问题(因为它看起来像是初学者引擎/框架设计问题),请提供访问器方法,该方法返回指向工作设备的指针,可以从中进一步传递它,需要使用它。

一个简单的例子来符合你在楼上的小"规范":

class Direct3DWin32 : public Renderer
{
      ID3D10Device* pD3DDevice;
  public:
      ID3D10Device* getD3DDevice();
}

现在,只要需要它,就可以在从 Direct3DWin32 实例获取它时通过函数传递它。引擎设计远不止于此,我个人不建议将其作为一条道路,但这是一个另一个时代的故事,也许是一系列书籍。

注意!

你可以像这样定义基本的东西,但是如果你真的想把多渲染路径设计提升到一个适当的水平,你将不得不引入多态性,添加一个很好的抽象级别。然后,您可以简单地定义一个统一的呈现接口,无论当前使用的是 DirectX 还是 OpenGL 渲染路径,它都会做正确的事情,实例化派生类并将其地址提供给指向其抽象基类的指针,该抽象基类包含所有内容都符合的指定接口。然后,您可以忽略 API 的基础选择。

希望这可以解决您当前的问题。此外,再次,回避全局。和快乐编码。

您可以使用双重调度的变体(又名访客模式):

class ShaderManager
{
public:
   void compileShader(Renderer* r, Shader* s) { r->compileShader(this, s); }
   void compileD3DShader(ID3D10Device* device, Shader*s);
   void compileGLShader(Shader* s);
};
class Renderer
{
public:
   virtual void compileShader(ShaderManager* m, Shader* s) = 0;
};
class Direct3dWin32 : public Renderer
{
private:
   ID3D10Device* m_device;
public:
   virtual void compileShader(ShaderManager* m, Shader* s)
   {
      m->compileD3DShader(m_device, s);
   }      
}
class OpenGLWin32 : public Renderer
{
public:
   virtual void compileShader(ShaderManager* m, Shader* s)
   {
      m->compileGLShader(s);
   }
}

(我不是"getters"的忠实粉丝。

您应该为要传递到另一个类的变量提供访问器方法。

例如,在 Direct3dWin32 中,您可以有:

ID3d10Device* get_gpd3Device()
{
    return g_pd3Device;
}

然后你可以把它传递给OpenGLWin32:

void useDevice (ID3d10Device* aDevice)
{
// do work
}

然后,使用这两个类的应用程序将负责弥合差距:

OpenGLWin32 openGL;
openGL.useDevice(direct3d.get_gpd3device());