我试图在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(在这里我使用了一些虚拟的VertexSphere3f类)。

问题很可能是(或至少也是)以下事实:

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/

10-15 04:54