2016-11-18 20 views
1

我想創建一個系統,在每個DLL中使用不同類的實現。所以我會有一個VertexBufferObject類,它有一個實現和私有方法(也許方法嚴格使用該DLL)。但是主要的可執行文件只會使用一些特定的方法。例如:在多個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,並且可以發現任何缺陷,但這不是問題的關鍵)。

+2

使用接口來表示公共API。 –

回答

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,但意圖不同:目標不是隱藏實現,而是分離,以避免在兩側進行派生和優化:在抽象上和在執行方面。

+0

謝謝!橋接模式系統看起來太複雜,並且會有更多的呼叫超過必要。速度很重要,所以我試圖限制函數調用次數,本地化數據,並可能限制內存。爲了速度,我想選項2可能是最好的。再次感謝。 –