C++:重写从模板类派生的虚拟纯函数

问题描述:

我写了一些基于此优秀访问者模式描述的类here(我的实现有点不同)。C++:重写从模板类派生的虚拟纯函数

template<typename... Types> 
class Visitable { 
public: 
    virtual void accept(Visitor<Types...>& visitor) = 0; 
}; 

class MyClass : public Visitable<int, string> 
{ 
    virtual void accept(Visitor<int, string>& visitor) 
    { 
      /*** my code ***/ 
    } 
}; 

这上面的代码工作,但我想实现MyClass这样的:

class MyClass : public Visitable<int, string> 
{ 
     template<typename... Types> 
     virtual void accept(Visitor<Types...>& visitor) 
     { 
       /*** my code ***/ 
     } 
}; 

显然我改变了调用accept方法,但我有此错误:“不能实例化抽象类” 。为什么在第二种情况下,accept()未被覆盖? MyClass应该模板化?

谢谢。

+0

模板不是函数,所以没有函数来覆盖基类函数。 –

使用CRTP:

template<class D, class...Ts> 
struct Visitable_CRTP : public Visitable<Ts...> { 
    virtual void accept(Visitor<Ts...>& visitor) override final { 
    return static_cast<D*>(this)->accept_impl(visitor); 
    } 
}; 
class MyClass : public Visitable_CRTP<MyClass, int, string> 
{ 
    template<typename... Types> 
    void accept_impl(Visitor<Types...>& visitor) // not virtual 
    { 
      /*** my code ***/ 
    } 
}; 

Visitor_CRTP写道,重视virtual accepttemplate accept_impl胶水代码。

如果你想有一个以上的accept方法,我们可以这样做:

template<class D, class...Visitables> 
struct PolyVisitable_CRTP {}; 

template<class D, class...V0, class...Vs> 
struct PolyVisitable_CRTP<D, Visitable<V0...>, Vs...> 
    Visitable_CRTP<D, V0...>, 
    PolyVisitable_CRTP<D, Vs...> 
{}; 

它可以这样使用:

class MyClass : 
    public PolyVisitable_CRTP<MyClass, 
    Visitable<int,double>, 
    Visitable<std::string, char, wchar_t>, 
    Visitable<> 
    > 
{ 
    template<typename... Types> 
    void accept_impl(Visitor<Types...>& visitor) 
    { 
      /*** my code ***/ 
    } 
}; 

和所有Visitable基地的accept S的意志被路由到accept_impl

未经测试或编译的代码,可能包含tpyos。

+0

至少“tpyos”一词包含一个错字:) –

+0

非常感谢你这个优秀的答案! – Milleras

事实上,你尝试实施

void VisitTable<int, string>::accept(Visitor<int, string>& visitor); 

void MyClass::accept<int, string>(Visitor<int, string>& visitor); 

在C++中,它是不一样的方法名字 - 一个带一个模版资格,其他没有。此外templatevirtual是不兼容的方法说明符和你应该有

class MyClass : ... { 
    ... 
    template<typename... Types> 
    virtual void accept(Visitor<Types...>& visitor); 
}; 

error: templates may not be ‘virtual’ 

错误的override C++ 11的关键字有助于避免这样的惊喜。

+0

你的评论我现在明白我的错误。谢谢。通常我使用'override',但在这里我忘了它。 – Milleras