我试图在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”:无法实例化abstract> class
1>与
1> [
1> TModel = Glyph3::Sphere3f,
1> TVertex =字形3::BasicVertexDX11::Vertex
1>]
1>由于以下成员:
1>'void Glyph3::AttributeEvaluator2f::evaluate(TModel&,TVertex&,float,float)':是抽象的
1>与
1> [
1> TModel = Glyph3::Sphere3f,
1> TVertex =字形3::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 =字形3::BasicVertexDX11::Vertex
1>]
1> c:\ program files(x86)\ Microsoft Visual Studio 11.0 \ vc \ include \ xmemory0(751):请参见对函数模板实例化'void std::allocator ::construct (_ Objty *,_ V0_t &&)'正在编译
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 ::construct (_ Objty *,_ V0_t &&)'正在编译
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(903):请参见对函数模板实例化的引用'void std::allocator_traits ::construct (std::allocator &,_ 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;
};
最佳答案
是的,有可能。类的定义看起来正确,您可以看到它们被正确编译为here(在这里我使用了一些虚拟的Vertex
和Sphere3f
类)。
问题很可能是(或至少也是)以下事实:
SurfacePositionFromSphere<BasicVertexDX11::Vertex> attribute();
实际上是在声明一个名为
attribute
的函数,该函数不接受任何参数并返回SurfacePositionFromSphere<BasicVertexDX11::Vertex>
类型的对象。稍后当您尝试访问该对象的成员函数时,编译器会抱怨(毕竟,您正在尝试访问函数指针的某些成员函数,这对于编译器而言毫无意义)。
为了创建对象而不是声明函数,请删除对象名称后的一对括号:
SurfacePositionFromSphere<BasicVertexDX11::Vertex> attribute;
// ^
// No parentheses
更新:
您正在通过以下方式声明属性 vector :
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>>()
);
关于c++ - 用部分模板专门化覆盖抽象成员函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15819019/