用部分模板特化重写抽象成员函数
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> [1> TModel = Glyph3:: Sphere3f,1> TVertex = Glyph3: BasicVertexDX11::顶点1> ]1>由于以下成员:1> 'void Glyph3::AttributeEvaluator2f::evaluate(TModel &,TVertex &,float,float)':是抽象的1> 与1> [1> TModel = Glyph3:: Sphere3f,1> TVertex = Glyph3: BasicVertexDX11::顶点1> ]1> c:userszij1fhdocumentsvisual studio 2012projectshg3trunkhieroglyph3sourcerendering AttributeEvaluator2f .h(26):见"Glyph3::AttributeEvaluator2f::evaluate"声明1> 与1> [1> TModel = Glyph3:: Sphere3f,1> TVertex = Glyph3: BasicVertexDX11::顶点1> ]1> c:program files (x86)microsoft visual studio 11.0vcincludexmemory0(751):参见参考函数模板实例化'void std::allocator<_Ty>::construct<_Objty,_Ty>(_Objty *,_V0_t &&)'正在编译1> 与1> [1> _ 泰= Glyph3:: AttributeEvaluator2f,1> _ Objty = Glyph3:: AttributeEvaluator2f,1> _ V0_t = Glyph3:: AttributeEvaluator2f1> ]1> c:program files (x86)microsoft visual studio 11.0vcincludexmemory0(751):参见参考函数模板实例化'void std::allocator<_Ty>::construct<_Objty,_Ty>(_Objty *,_V0_t &&)'正在编译1> 与1> [1> _ 泰= Glyph3:: AttributeEvaluator2f,1> _ Objty = Glyph3:: AttributeEvaluator2f,1> _ V0_t = Glyph3:: AttributeEvaluator2f1> ]1> c:program files (x86)microsoft visual studio 11.0vcincludexmemory0(903):参见参考函数模板实例化'void std::allocator_traits<_Alloc>::construct<_Ty>(std:: allocator_trait<_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>>()
);
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- 无法创建抽象类的实例
- 如何定义一个纯抽象基类
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 用pybind11包装C++抽象类时出错
- 在 C++ 中用派生类型重写成员函数
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 方法重写线程C++中的概念
- 为重写std::exception的库生成swig接口时出错
- C++:从抽象类重写纯虚拟运算符重载
- 我将如何通过抽象类传递虚拟方法,但可以选择不重写
- 重写指向抽象类的指针的引用值无效
- C++在基类本身中重写基类的抽象方法
- 如何重写调用另一个抽象类的抽象类的虚拟函数
- 如何使用协变参数重写函数(在抽象基类中)
- 我可以拥有一个必须从非抽象基重写的虚拟函数吗
- 将抽象重写的方法传递给Boost::Thread
- 抽象类类型.是不允许的,纯虚函数是不重写的
- 用部分模板特化重写抽象成员函数