1

小さな 3D エンジンを再構築したいのですが、非常に小さいので、すべてのファイルを 1 つのプロジェクトに配置します。今、私はそれをインターフェイスで再構築したいので、さまざまなモジュールをさまざまなプロジェクトに分散させ、それらをdllとしてビルドできます。そうするとき、私はフレームワーク コードの基本設計で多くの困難に遭遇しました。私の小さなエンジンの「オブジェクト階層」を設計したいのですが、それは前作で実現しました。例えば:

Object
Component
SceneComponent
StaticMeshComponent/SkelMeshComponent
D3DSkelComponent 
...

しかし、それらは直接実装されています。今、私はインターフェイス(純粋な仮想クラス)を使用したいので、基本的なインターフェイス(テスト用)を設計しています:

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

class IObject
{
public:
    virtual std::string GetName() = 0;
};

class IMesh : public IObject
{
public:
    virtual void Draw() = 0;
};

class IStaticMesh : public IMesh
{
public:    
    virtual void BuildSomeMesh() = 0;
};

class ISkeletalMesh : public IMesh
{
public:
    virtual void PlayAnim( const std::string& strAnimName ) = 0;
};

class ID3DSkeletalMesh : public ISkeletalMesh
{
public:
    virtual void LoadD3D( const std::string& strD3D ) = 0;
};

大丈夫そうに見えますが、実装しようとすると、不可能なミッションになる可能性があります。まず、IObject のテンプレート クラスまたは通常のクラスを記述できます。

template < typename TBase >
class TObject : public TBase
{
public:
    virtual std::string GetName()
    {
        return m_strTest;
    }

    std::string m_strTest;
};

この TObject に基づいて、CMesh を実装できます。

class CMesh : public TObject< IMesh >
{
public:
    virtual void Draw()
    {
        cout<<"draw mesh" <<endl;
    }
};
   IMesh* pMesh = new CMesh();  // ok
   IObject* pObj = pMesh;      // ok

これまでのところ、うまく機能しています。しかし、CStaticMesh/CSkeletalMesh/CD3DSkeletalMesh を実装する方法は? それは多分このようです:

class CStaticMesh : public CMesh, public IStaticMesh
{
public:

};

しかし、私は2つのIObject基本クラスを持っているので、すべての「public xxx」を「virtual public xxx」に変更する必要があります。見栄えが悪いです。もう 1 つの質問は、CStaticMesh が IStaticMesh のすべての仮想メンバー関数を実装する必要があることです。

virtual void Draw() = 0;
virtual void BuildSomeMesh() = 0;

CStaticMesh のベース コールである CMesh に Draw があっても。わかりました、多分私は TMesh が必要です:

template < typename TBase >
class TMesh : public TObject< TBase >
{
public:
    virtual void Draw()
    {
        cout<<"draw mesh" <<endl;
    }
};

CStaticMesh を次のように実装します。

class CStaticMesh : public TMesh<IStaticMesh>
{
public:
    virtual void BuildSomeMesh()
    {
        cout<<"Build Some Mesh!"<<endl;
    }
};

問題ないように見えますが、CD3DSkeletalMesh を実装するにはどうすればよいですか? TSkeletalMesh を作成しますか? わかりました、それはクレイジーです!!!

これがアビメだと思います。この設計の間違いはどれですか。このジレンマを回避するためにデザインのアイデアを変更するにはどうすればよいでしょうか? これらのインターフェースの継承階層を維持し、簡単に実装できるアイデアを知っていますか? 多くの仮想継承を使用する場合、パフォーマンスの問題はありますか?

4

1 に答える 1

0

あなたが言ったように、仮想継承でこれを解決することができます。これにより、階層内に複数継承されたインターフェイスクラスのインスタンスが1つだけ作成されます。

まず、インターフェース:

class IObject
{
public:
    virtual std::string GetName() = 0;
};

class IMesh : virtual public IObject
{
public:
    virtual void Draw() = 0;
};

class IStaticMesh : virtual public IMesh
{
public:    
    virtual void BuildSomeMesh() = 0;
};

class ISkeletalMesh : virtual public IMesh
{
public:
    virtual void PlayAnim( const std::string& strAnimName ) = 0;
};

class ID3DSkeletalMesh : virtual public ISkeletalMesh
{
public:
    virtual void LoadD3D( const std::string& strD3D ) = 0;
};

次に、実装:

class CObject : virtual public IObject
{
public:
    std::string GetName()
    {
        return m_strTest;
    }

    std::string m_strTest;
};

class CMesh : public CObject, virtual public IMesh
{
public:
    void Draw()
    {
        cout<<"draw mesh" <<endl;
    }
};

class CStaticMesh : public CMesh, virtual public IStaticMesh
{
public:
    void BuildSomeMesh()
    {
        cout<<"Build Some Mesh!"<<endl;
    }    
};
...

これによるパフォーマンスへの影響については、この質問を参照してください。

于 2012-10-21T14:19:04.450 に答える