多个DLL中的单独类实现

时间:2016-11-18 20:04:02

标签: c++ class methods dll class-design

我正在尝试创建一个在每个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,并且可以发现其中的任何缺陷都很酷,但不是问题的重点。)

1 个答案:

答案 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抽象和实现方面。