1

我正在尝试在 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' : cannot instantiate abstract >class 1> with 1> [ 1> TModel =Glyph3::Sphere3f, 1> TVertex=Glyph3::BasicVertexDX11::Vertex 1> ] 1> 由于以下成员: 1> 'void Glyph3::AttributeEvaluator2f::evaluate(TModel &,TVertex &,float,float)' : 是抽象的 1> with 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:\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=字形3::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:\program文件 (x86)\microsoft visual studio 11.0\vc\include\xmemory0(903) :参见对函数模板实例化的参考 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' 正在编译\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:\program files (x86)\ microsoft visual studio 11.0\vc\include\xmemory0(903):参见对函数模板实例化的引用 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *, _V0_t &&)' 正在编译\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:\program files (x86)\ microsoft visual studio 11.0\vc\include\xmemory0(903):参见对函数模板实例化的引用 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *, _V0_t &&)' 正在编译请参阅对函数模板实例化 '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:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(903) :参见对函数模板实例化的参考void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' 正在编译请参阅对函数模板实例化 '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:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0(903) :参见对函数模板实例化的参考void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' 正在编译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<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' 的引用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<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' 的引用请参阅正在编译的函数模板实例化 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' 的引用请参阅正在编译的函数模板实例化 'void std::allocator_traits<_Alloc>::construct<_Ty,_Ty>(std::allocator<_Ty> &,_Objty *,_V0_t &&)' 的引用

EDIT2:上面指出的用法不正确(正如安迪指出的那样)。这是我的确切用法:

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;
};
4

1 回答 1

2

所以问题是,是否有可能以这种方式覆盖抽象基类方法参数的类型?

是的,有可能。你的类的定义看起来是正确的,你可以在这里看到它们被正确编译(我使用了一些虚拟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>>()
    );
于 2013-04-04T18:58:42.793 回答