2016-11-18 40 views
1

各DLLでクラスの実装が異なるシステムを作成しようとしています。だから私は1つの実装とプライベートメソッド(と多分そのDLLによって厳密に使用されるメソッド)を持つVertexBufferObjectクラスを持っていただろう。しかし、ある種のメソッドだけがメインの実行可能ファイルによって使用されます。たとえば、次のようにopenglGraphics.dllで複数のDLLで別々のクラス実装を実装する

:directXGraphics.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(); 
}; 

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、さらに別のプロジェクトにさえなります。しかし...

クライアントはオブジェクトの定義を知っていなければならず、ODRルールは1つの定義のみを必要とするため、これはDLLクライアント側では機能しません。

したがって、改訂された、より持続可能なデザインを選択する方がよいでしょう。

オプション1:openglGraphics.dllでパブリックインターフェイス

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 !!! 
}; 

の使用継承:

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(); 
}; 

VertexBufferGLObjectをソフトウェア構成に応じて右DLLをロードし、作成することができ、工場クライアントコードは多態性基底クラスのみを使用します。

ただし、クライアントコードではポインタと参照のみが使用されます。コピーが必要な場合は、スライスする危険性を避けるために、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がベストかもしれないと思います。再度、感謝します。 –

関連する問題