我正在尝试创建一个在每个dll中使用不同类的实现的系统。所以我有一个VertexBufferObject类,它有一个实现和私有方法(可能是该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();
};
最后,可执行文件可以使用工厂函数并创建类的导出方法,但不能创建特定于dll的方法。这可能吗?还有另一种处理方法吗? (另外,如果您使用的是图形API,并且可以发现其中的任何缺陷都很酷,但不是问题的重点。)
答案 0 :(得分:1)
当然可以在DLL端执行此操作:您的每个实现都将位于单独的编译单元和单独的DLL中,甚至是单独的项目。但是......
但这不适用于DLL客户端,因为客户端必须知道对象的定义,而ODR规则只需要一个定义。
因此,您最好选择经过修订且更具可持续性的设计。
选项1:使用公共接口的继承
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,而客户端代码只使用多态基类。
然而,暗示客户端代码仅使用指针和引用。如果需要复制,如果您想避免切片风险,则需要使用clone()
功能。
选项2:隐藏内部结构的更大灵活性
您还可以使用PIMPL idiom也称为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
};
你的间接水平更高。但是这个类的实现会将调用转发给IVertexBuffer对象,你可以使用工厂来创建私有对象,如选项1所示。优点是客户端可以将VertexBufferObject用作任何其他对象(按值或通过引用) ):它在封装/隔离方面更进一步。
选项3:使用网桥设计模式
bride design pattern旨在将抽象与其实现分离。
它在工作方式上类似于选项2,但意图不同:目标不是隐藏实现,而是解耦,以避免双方的推导和细化:on the抽象和实现方面。