簡體   English   中英

用部分模板專門化覆蓋抽象成員函數

[英]Overriding an abstract member function with partial template specialization

我試圖在C ++中實現特定的模板設計,並且遇到了一個我想解決的問題。 這是設置,並說明了要解決的問題。

我聲明了一個模板化抽象基類,如下所示:

template <class TModel, class TVertex>
class AttributeEvaluator2f
{
public:
    virtual void evaluate( TModel& model, TVertex& v, float x, float y ) = 0;
};

然后,我想實現專門用於模板參數之一的子類,如下所示:

template <class TVertex>
class SurfacePositionFromSphere : public AttributeEvaluator2f<Sphere3f,TVertex>
{
public:
    virtual void evaluate( Sphere3f& sphere, TVertex& v, float theta, float phi )
    {
        sphere.SamplePosition( v.position, theta, phi );
    };
};

然后,我將基於這些類實例化一個對象,如下所示:

SurfacePositionFromSphere<BasicVertexDX11::Vertex> attribute();

編譯錯誤指示我從未在原始基類中實現抽象方法。 這可能是因為在子類中,我直接使用第一個已聲明為專用的參數聲明了該方法(在本例中為Sphere3f )。

所以問題是,是否可以通過這種方式覆蓋抽象基類方法參數的類型? 如果不是,是否有類似的機制可用於提供類似的功能?

在此先感謝您的幫助!

編輯:由於模板解包,確切的錯誤消息是巨大的,但這是它的主要部分供您參考:錯誤C2259:'Glyph3 :: AttributeEvaluator2f':無法使用1> [1> TModel實例化抽象> class 1> = Glyph3 :: Sphere3f,1> TVertex = Glyph3 :: BasicVertexDX11 :: Vertex 1>] 1>由於以下成員:1>'void Glyph3 :: AttributeEvaluator2f :: evaluate(TModel&,TVertex&,float,float)' :是抽象1>帶有1> [1> TModel = Glyph3 :: Sphere3f,1> TVertex = Glyph3 :: BasicVertexDX11 :: Vertex 1>] 1> c:\\ users \\ zij1fh \\ documents \\ visual studio 2012 \\ projects \\ hg3 \\ trunk \\ hieroglyph3 \\ source \\ rendering \\ attributeevaluator2f.h(26):參見'Glyph3 :: AttributeEvaluator2f :: evaluate'1>的聲明,其中1> [1> TModel = Glyph3 :: Sphere3f,1> TVertex = Glyph3 :: BasicVertexDX11 :: Vertex 1>] 1> c:\\程序文件(x86)\\ Microsoft Visual Studio 11.0 \\ vc \\ include \\ xmemory0(751):請參見對函數模板實例化的引用'void std :: allocator <_Ty> :: construct <_Objty,_Ty>(_ Objty *,_ V0_t &&)'正在編譯 d 1>帶有1> [1> _Ty = Glyph3 :: AttributeEvaluator2f,1> _Objty = Glyph3 :: AttributeEvaluator2f,1> _V0_t = Glyph3 :: AttributeEvaluator2f 1>] 1> c:\\ program files(x86)\\ Microsoft Visual Studio 11.0 \\ vc \\ include \\ xmemory0(751):請參見對函數模板實例化'void std :: allocator <_Ty> :: construct <_Objty,_Ty>(_ Objty *,_ V0_t &&)'的引用,其中1>編譯為1> [ 1> _Ty = Glyph3 :: AttributeEvaluator2f,1> _Objty = Glyph3 :: AttributeEvaluator2f,1> _V0_t = Glyph3 :: AttributeEvaluator2f 1>] 1> c:\\程序文件(x86)\\ Microsoft Visual Studio 11.0 \\ vc \\ include \\ xmemory0 (903):請參見對正在編譯的函數模板實例化'void std :: allocator_traits <_Alloc> :: construct <_Ty,_Ty>(std :: allocator <_Ty>&,_ Objty *,_ V0_t &&)的引用

EDIT2:上面指示的用法不正確(如Andy指出的)。 這是我的確切用法:

VertexEvaluator2f< Sphere3f, BasicVertexDX11::Vertex > evaluator;
evaluator.Evaluators.push_back( SurfacePositionFromSphere<BasicVertexDX11::Vertex>() );

在VertexEvaluator2f類中,我遍歷屬性以生成一個頂點。 為了完整起見,這也是該類的聲明:

template <class TModel, class TVertex>
class VertexEvaluator2f
{
public:
    void SetModel( TModel& model ) {
        m_Model = model;
    };

    void evaluate( TVertex& v, float x, float y ) {
        for ( auto& evaluator : Evaluators ) {
            evaluator.evaluate( m_Model, v, x, y );
        }
    };

    std::vector< AttributeEvaluator2f< TModel, TVertex > > Evaluators;

protected:
    TModel m_Model;
};

所以問題是,是否可以通過這種方式覆蓋抽象基類方法參數的類型?

對的,這是可能的。 類的定義看起來正確,您可以在此處看到它們的編譯正確(在這里我使用了一些虛擬的VertexSphere3f類)。

問題很可能是(或至少也是)以下事實:

SurfacePositionFromSphere<BasicVertexDX11::Vertex> attribute();

實際上是在聲明一個名為attribute函數 ,該函數不接受任何參數並返回SurfacePositionFromSphere<BasicVertexDX11::Vertex>類型的對象。

稍后當您嘗試訪問該對象的成員函數時,編譯器會抱怨(畢竟,您正在嘗試訪問函數指針的某些成員函數,這對於編譯器而言毫無意義)。

為了創建對象而不是聲明函數,請刪除對象名稱后的一對括號:

SurfacePositionFromSphere<BasicVertexDX11::Vertex> attribute;
//                                                          ^
//                                             No parentheses

更新:

您正在通過以下方式聲明屬性向量:

std::vector< AttributeEvaluator2f< TModel, TVertex > > Evaluators;

與所有標准容器一樣, std::vector<>具有值語義 這意味着它將包含類型為AttributeEvaluator2f< TModel, TVertex >對象(而不是指向對象的指針!),並且該類確實是抽象的。

在這種情況下,您想要的是使用(智能)指針,例如:

#include <memory>

template <class TModel, class TVertex>
class VertexEvaluator2f
{
    // ...

    void evaluate( TVertex& v, float x, float y ) {
        for ( auto& evaluator : Evaluators ) {
            evaluator->evaluate( m_Model, v, x, y );
        //           ^^
        }
    };

    std::vector<
        std::shared_ptr<AttributeEvaluator2f<TModel, TVertex>>
    //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        > Evaluators;

protected:
    TModel m_Model;
};

這就是將元素添加到集合中的方式:

VertexEvaluator2f< Sphere3f, BasicVertexDX11::Vertex > evaluator;
evaluator.Evaluators.push_back( 
    std::make_shared<SurfacePositionFromSphere<BasicVertexDX11::Vertex>>()
    );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM