在多个 DLL 中分离 class 个实现
Separate class implementations in multiple DLLs
我正在尝试创建一个系统,该系统在每个 dll 中使用 class 的不同实现。所以我有一个 VertexBufferObject class,它有一个实现和私有方法(也许是该 DLL 严格使用的方法)。但是主要可执行文件只会使用一组特定的方法。例如:
在openglGraphics.dll中:
class VertexBufferObject {
private:
// Unexported data
uint vbo;
// Exported data (won't actually use this though)
std::vector<Vec3> arr;
public:
// Unexported methods
IDirect3DVertexBuffer9 *getVBO();
// Exported methods
virtual void Build(Vec2 array);
virtual void Build(Vec3 array);
virtual void Unbind();
~VertexBufferObject();
};
在directXGraphics.dll中:
class VertexBufferObject {
private:
// Unexported data
IDirect3DVertexBuffer9 vbo;
// Exported data (won't actually use this though)
std::vector<Vec3> arr;
public:
// Unexported methods
IDirect3DVertexBuffer9 *getVBO();
// Exported methods
virtual void Build(Vec2 array);
virtual void Build(Vec3 array);
virtual void Unbind();
~VertexBufferObject();
};
最后,可执行文件可以使用工厂函数并创建 class 的导出方法,但不能创建特定于 dll 的方法。这可能吗?还有其他方法可以处理吗? (此外,如果您对图形 API 感兴趣并且可以发现其中的任何缺陷,那会很酷,但不是问题的重点。)
当然可以在 DLL 端执行此操作:您的每个实现都将在一个单独的编译单元和一个单独的 DLL,甚至一个单独的项目中。但是...
但这在DLL客户端是行不通的,因为客户端必须知道对象的定义,而ODR规则要求只有一个定义。
因此,您最好选择经过修改且更具可持续性的设计。
选项1:use继承public接口
class IVertexBuffer {
public:
// Exported methods
virtual void Build(Vec2 array)=0;
virtual void Build(Vec3 array)=0;
virtual void Unbind()=0;
virtual ~IVertexBuffer(); // virtual function ==> virtual dtor !!!
};
在openglGraphics.dll中:
class VertexBufferGLObject : public IVertexBuffer {
private:
uint vbo;
std::vector<Vec3> arr;
public:
// Unexported methods
IDirect3DVertexBuffer9 *getVBO();
// Exported methods of the interface
void Build(Vec2 array) override;
void Build(Vec3 array) override;
void Unbind() override;
~VertexBufferObject();
};
工厂可以根据软件配置加载正确的 dll,并创建 VertexBufferGLObject ,而客户端代码只会使用多态基础 class。
然而,这意味着客户端代码仅使用指针和引用。如果需要复制,如果你想避免切片的风险,你需要使用 clone()
函数。
选项 2:更灵活地隐藏内部结构
您也可以使用 PIMPL idiom also called compilation firewall。
想法如下:
class IVertexBufferImpl; // you need to define this only in the implementation
class VertexBufferObject {
private:
IVertexBufferImpl *myobject;
public:
// Exported methods
virtual void Build(Vec2 array);
virtual void Build(Vec3 array);
virtual void Unbind();
virtual ~VertexBufferObject();
// + rule of 3
};
你的间接水平更高了。但是这个 class 的实现会将调用转发给 IVertexBuffer 对象,您可以像选项 1 中那样使用工厂创建私有对象。优点是客户端可以将 VertexBufferObject 用作任何其他对象(通过值或参考):它在 encapsulation/isolation 中更进一步。
方案三:使用桥梁设计模式
bride design pattern 旨在将抽象与其实现解耦。
它的工作方式与选项2类似,但意图不同:目标不是隐藏实现,而是解耦,以避免双方的推导和细化:在抽象和在实施方面。
我正在尝试创建一个系统,该系统在每个 dll 中使用 class 的不同实现。所以我有一个 VertexBufferObject class,它有一个实现和私有方法(也许是该 DLL 严格使用的方法)。但是主要可执行文件只会使用一组特定的方法。例如:
在openglGraphics.dll中:
class VertexBufferObject {
private:
// Unexported data
uint vbo;
// Exported data (won't actually use this though)
std::vector<Vec3> arr;
public:
// Unexported methods
IDirect3DVertexBuffer9 *getVBO();
// Exported methods
virtual void Build(Vec2 array);
virtual void Build(Vec3 array);
virtual void Unbind();
~VertexBufferObject();
};
在directXGraphics.dll中:
class VertexBufferObject {
private:
// Unexported data
IDirect3DVertexBuffer9 vbo;
// Exported data (won't actually use this though)
std::vector<Vec3> arr;
public:
// Unexported methods
IDirect3DVertexBuffer9 *getVBO();
// Exported methods
virtual void Build(Vec2 array);
virtual void Build(Vec3 array);
virtual void Unbind();
~VertexBufferObject();
};
最后,可执行文件可以使用工厂函数并创建 class 的导出方法,但不能创建特定于 dll 的方法。这可能吗?还有其他方法可以处理吗? (此外,如果您对图形 API 感兴趣并且可以发现其中的任何缺陷,那会很酷,但不是问题的重点。)
当然可以在 DLL 端执行此操作:您的每个实现都将在一个单独的编译单元和一个单独的 DLL,甚至一个单独的项目中。但是...
但这在DLL客户端是行不通的,因为客户端必须知道对象的定义,而ODR规则要求只有一个定义。
因此,您最好选择经过修改且更具可持续性的设计。
选项1:use继承public接口
class IVertexBuffer {
public:
// Exported methods
virtual void Build(Vec2 array)=0;
virtual void Build(Vec3 array)=0;
virtual void Unbind()=0;
virtual ~IVertexBuffer(); // virtual function ==> virtual dtor !!!
};
在openglGraphics.dll中:
class VertexBufferGLObject : public IVertexBuffer {
private:
uint vbo;
std::vector<Vec3> arr;
public:
// Unexported methods
IDirect3DVertexBuffer9 *getVBO();
// Exported methods of the interface
void Build(Vec2 array) override;
void Build(Vec3 array) override;
void Unbind() override;
~VertexBufferObject();
};
工厂可以根据软件配置加载正确的 dll,并创建 VertexBufferGLObject ,而客户端代码只会使用多态基础 class。
然而,这意味着客户端代码仅使用指针和引用。如果需要复制,如果你想避免切片的风险,你需要使用 clone()
函数。
选项 2:更灵活地隐藏内部结构
您也可以使用 PIMPL idiom also called compilation firewall。
想法如下:
class IVertexBufferImpl; // you need to define this only in the implementation
class VertexBufferObject {
private:
IVertexBufferImpl *myobject;
public:
// Exported methods
virtual void Build(Vec2 array);
virtual void Build(Vec3 array);
virtual void Unbind();
virtual ~VertexBufferObject();
// + rule of 3
};
你的间接水平更高了。但是这个 class 的实现会将调用转发给 IVertexBuffer 对象,您可以像选项 1 中那样使用工厂创建私有对象。优点是客户端可以将 VertexBufferObject 用作任何其他对象(通过值或参考):它在 encapsulation/isolation 中更进一步。
方案三:使用桥梁设计模式
bride design pattern 旨在将抽象与其实现解耦。
它的工作方式与选项2类似,但意图不同:目标不是隐藏实现,而是解耦,以避免双方的推导和细化:在抽象和在实施方面。