![](/img/trans.png)
[英]Template partial specialization for multiple types overriding member function
[英]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;
};
所以問題是,是否可以通過這種方式覆蓋抽象基類方法參數的類型?
對的,這是可能的。 類的定義看起來正確,您可以在此處看到它們的編譯正確(在這里我使用了一些虛擬的Vertex
和Sphere3f
類)。
問題很可能是(或至少也是)以下事實:
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.