简体   繁体   English

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

[英]C++: Overriding virtual pure function derived from a template class

I wrote some classes based on this excellent visitor pattern described here (my implementation is a little bit different). 我根据此处描述的出色访客模式编写了一些类(我的实现有些不同)。

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 ***/
     }
};

This code above works but I would like implement MyClass like that: 上面的代码可以工作,但是我MyClass这样实现MyClass

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

Obviously I changed the call to the accept method but I have this error: " cannot instantiate abstract class ". 显然,我将调用更改为accept方法,但是出现了以下错误:“ 无法实例化抽象类 ”。 Why in this second case, accept() is not overridden ? 为什么在第二种情况下, accept()不被覆盖? MyClass should be templated ? MyClass应该模板化吗?

Thanks. 谢谢。

Use the CRTP: 使用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 writes the glue code that attaches virtual accept to your template accept_impl . Visitor_CRTP编写将virtual accept附加到template accept_impl的粘合代码。

If you want to have more than one accept method, we can do this: 如果您想使用多个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...>
{};

which can be used like this: 可以这样使用:

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 ***/
  }
};

and all of the Visitable bases's accept s will be routed to accept_impl . 并且所有Visitable bases的accept都将路由到accept_impl

Code not tested or compiled, probably contains tpyos. 未经测试或编译的代码,可能包含tpyos。

In fact you try to implement 实际上,您尝试实施

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

with

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

In C++ it is not the same method name - one has a template qualification and the other not. 在C ++中,方法名称不同-一个具有模板资格,另一个没有。 Moreover template and virtual are incompatible specifiers for methods and you should have an error for 而且templatevirtual是方法的不兼容说明符,您应该为

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

error: templates may not be ‘virtual’

The override C++11 keyword helps to avoid such surprises. override C ++ 11关键字有助于避免此类意外情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM