我可以将CRTP与多个派生类一起使用,并以多态方式使用它们吗?

时间:2016-04-15 08:49:41

标签: c++ templates inheritance virtual-functions crtp

我有这样的类层次结构:

template <class Type>
class CrtpBase
{
protected:
    Type& real_this()
    {
        return static_cast<Type&>(*this);
    }
};

template <class ChildType>
class Base : CrtpBase<ChildType>
{
public:
    void foo()
    {
        this->real_this().boo();
    }
};

class Derived1 : public Base<Derived1>
{
public:
    void boo { ... }
};

class Derived2 : public Base<Derived2>
{
public:
    void boo { ... }
};

问题是,我想以这种方式使用我的课程:

std::vector<Base*> base_vec;
base_vec.push_bach(new Derived1());
base_vec.push_bach(new Derived2());
.........
base_vec[0]->foo();

但这是不可能的,因为所有派生类的基类都不同(实际上Base并不是一个类型,它的模板)。那么,有没有办法将crtp与多个派生类一起使用,以及多态?

1 个答案:

答案 0 :(得分:4)

确实有,你需要添加适当的非模板基类:

class AbstractBase
{
public:
  virtual ~AbstractBase() {}

  virtual void foo() = 0;
};


template <class ChildType>
class Base : CrtpBase<ChildType>, public AbstactBase
{
  void foo() override { this->real_this().boo(); }
};

然后,将您的向量声明为std::vector<AbstractBase*>

这确实引入了动态调度的开销(您可能试图通过使用CRTP来避免),但动态调度是在C ++中获取运行时多态性的唯一方法。

但是,它仍然可能是有益的。例如,如果foo的实现由所有派生类共享,但调用许多不同的boo样式函数(每个派生类具有不同的实现),您只需支付调用foo时动态调度成本,然后在 foo中进行的所有调用静态调度,CRTP样式。

另一方面,如果只是在boo内调用类似foo的函数,您也可以将boo设为虚拟,放置非虚拟{{1}进入基地,从而摆脱CRTP。然后,成本将是相同的:非虚拟调度(foo)和虚拟调度(foo)。

旁注,您应该强烈考虑在boo中存储智能指针; 拥有原始指针是不好的做法。