4

はい、私は以前にダイヤモンドの継承を扱ったことがありますが、今回の私の問題はかなり独特のようでした。基本クラスとして機能するIShaderResourceというインターフェイスがあります。IVertexBufferと呼ばれるIShaderResourceから派生した別のインターフェイスがあります。次に、IShaderResourceから派生したD3D11ShaderResourceと呼ばれる基本インターフェイスの実装があります。その後、D3D11ShaderResourceを拡張し、IVertexBufferを実装するD3D11VertexBufferというオブジェクトがあります。これで、私の階層は次のようになります。

                                IShaderResource
                                   /        \
                                  /          \
                         IVertexBuffer     D3D11ShaderResource
                                  \          /
                                   \        /
                                D3D11VertexBuffer

IShaderResourceには、純粋仮想関数が1つだけあります。これが通常のダイヤモンド継承と異なる部分は、IVertexBufferがその関数を実装していないことです。D3D11ShaderResourceがその機能を実装しているのに対し、それは抽象のままです。IShaderResourceを両方の派生クラスに仮想的に継承する場合でも、抽象関数が不足していると見なされます。システムを機能させるには、IVertexBufferをIShaderResourceから派生させる必要があります。実装は、実行時に動的にロードされるdllに含まれますが、プログラムの存続期間中はリンクされたままになります。したがって、dllから作成されたオブジェクトは、インターフェイスを介してどこからでもアクセスできますが、インターフェイスの背後では、プログラムの存続期間を通じて型が定義されます。例えば、d3d11ライブラリをロードして頂点バッファーを作成した場合、D3D11VertexBufferのインスタンスを指すIVertexBuffer ptrが返され、その後、他の実装された頂点バッファーの実装はできなくなります。これは、レンダラー内で、IShaderResourceをD3D11ShaderResourceにキャストして、それがどうなるかを十分に理解できることを意味します。(注*レンダラーの外部でこれを行うと、インターフェイスの目的が無効になります)

Rendererインターフェイスには、IVertexBufferのようなIShaderResourceを渡し、D3D11ShaderResource部分のみを介して基になるD3D11VertexBufferでアクションを実行したい関数がありますが、他の関数はIVertexBufferを受け取り、D3D11Vertexbufferでアクションを実行します。そのためには、IShaderResourceから派生して、D3D11ShaderResourceが完全なタイプのIShaderResourceであることを確認すると同時に、D3D11VertexBufferがIVertexBufferとD3D11ShaderResourceの両方から継承するようにする必要があります。

ここでは4000行のコードをプッシュしているので、問題のある抜粋を投稿します。

IShaderResource

class IShaderResource
{
public:
    struct INIT_DESC
    {
        SYNC_USAGE usage;
    };

public:
    // virtual destructor for derived classes
    virtual ~IShaderResource() {}

    // the resource usage hint
    virtual IRenderUtility::SYNC_USAGE GetUsageType() = 0;
};

IVertexBuffer

class IVertexBuffer : 
    public virtual IShaderResource
{
public:
    struct INIT_DESC : public IShaderResource::INIT_DESC
    {
        const void * Data;
        unsigned int ByteWidth;
        unsigned int ByteStride;
    };

public:
    // virtual destructor for derived classes
    virtual ~IVertexBuffer() {}

    // the resource usage hint
    virtual IRenderUtility::SYNC_USAGE GetUsageType() = 0;
};

D3D11ShaderResource

class D3D11RenderUtility::D3D11ShaderResource : 
    public virtual IRenderUtility::IShaderResource
{
public:
    struct INIT_DESC
    {
        IRenderUtility::SYNC_USAGE usage;
        ID3D11ShaderResourceView * resourceView;
    };

public:
    // default constructor
    D3D11ShaderResource(INIT_DESC & desc) : 
        m_Usage(desc.usage),
        m_ResourceView(desc.resourceView)
        {}

    // virtual destructor for derived classes
    virtual ~D3D11ShaderResource() {}

    // obtains the resource usage hint
    IRenderUtility::SYNC_USAGE GetUsageType() {return m_Usage;}

    // used to obtain the resource view of the object
    ComPtr<ID3D11ShaderResourceView> GetResourceView() const {return m_ResourceView;}

protected:
    IRenderUtility::SYNC_USAGE m_Usage;
    ComPtr<ID3D11ShaderResourceView> m_ResourceView;
};

D3D11VertexBuffer

class D3D11RenderUtility::D3D11VertexBuffer : 
    public IRenderUtility::IVertexBuffer ,
    public D3D11RenderUtility::D3D11ShaderResource
{
public:
    struct INIT_DESC : 
        public D3D11ShaderResource::INIT_DESC
    {
        ID3D11Buffer * buf;
    };

private:
    // disable copy constructor 
    D3D11VertexBuffer(const D3D11VertexBuffer & buf);

    // disable assignment operator
    void operator=(const D3D11VertexBuffer & buf);  

public:
    // default constructor
    D3D11VertexBuffer(INIT_DESC & desc) :
        D3D11ShaderResource(desc),
        m_Buffer(desc.buf)
        {}

    // virtual destructor for derived classes
    virtual ~D3D11VertexBuffer() {}

    // used to obtain the d3d11 vertex buffer pointer
    ComPtr<ID3D11Buffer> GetBuffer() const {return m_Buffer;}

private:
    ComPtr<ID3D11Buffer> m_Buffer;
};

IRenderUtility :: SYNC_USAGEは、フレームワークのさらに上の単純な列挙型であり、ComPtrは、comポインターを自動的に解放するために作成した小さなスマートラッパーです。それ以外は、残りはかなり明白です。

ところで、実際のエラーはこれです: error C2259: 'SYNC::D3D11RenderUtility::D3D11VertexBuffer' : cannot instantiate abstract class 2> due to following members: 2> 'SYNC::IRenderUtility::SYNC_USAGE SYNC::IRenderUtility::IVertexBuffer::GetUsageType(void)' : is abstract

SYNCは、これらすべてが含まれる名前空間です。

4

2 に答える 2

2

GetUsageTypeinの宣言を削除する必要があると思いますIVertexBuffer。そこにあるのと base にあるのは冗長なようIShaderResourceです。

于 2013-02-19T20:42:37.887 に答える
1

ここで使用しているのは、言語定義で「優位性」と呼ばれるものです。2 つの中間クラスの 1 つだけが、仮想ベースで定義された仮想関数をオーバーライドする場合、その定義は派生クラスにも適用されます。@chuex が言ったように、IVertexBuffer の冗長な宣言を削除する必要があります。これは、優位性が適用される前提を壊すためです。

読みやすさやその他の理由で冗長なコードを追加することは、メンテナンスが難しくなるという理由だけで、通常は悪い考えです。ここでは、クラス階層がやろうとしていることを無効にします。

于 2013-02-19T23:44:36.153 に答える