【问题标题】:Using CRTP with an interface将 CRTP 与接口一起使用
【发布时间】:2017-04-16 01:08:54
【问题描述】:

我有一组实现相同业务方法的类。由于性能原因,我计划使用 CRTP 而不是虚拟调度。但我想将编码的便利性保留在带有继承和虚拟方法的单个接口中。

是否可以让我的专用类既继承自模板化抽象类(使用 CRTP 来保存公共代码),又继承自纯虚拟类,这样我就可以创建每种类型的实例但让我的客户端代码依赖只在界面上?更好的是,如何使用 CRTP 为客户端代码提供单个接口,同时拥有多个实现?

【问题讨论】:

  • 好吧,如果你计划重构你的代码由于性能原因抽象方法不是一个好主意......你使用 CRTP 来避免虚拟调度,这就是为什么它的常见替代名称是静态多态性。当然从句法的角度来看,没有人可以阻止你这样做,但恕我直言,你需要仔细考虑......
  • 公共方法不会在接口中,只在特化中。

标签: c++ c++11 inheritance crtp pure-virtual


【解决方案1】:

当然。您可以使用这样的方法,这是完全有效的:

class Interface 
{
public:
    virtual void doSomething() = 0;
    //...
};

template<typename T>
class GeneralImpl : public Interface
{
public:

    void doSomething() override
    {
        auto someDetail = T::somethingStatic();
        //...
        static_cast<T*>(this)->someMember();
        //...
    }
}

class SpecificImpl : public GeneralImpl<SpecificImpl>
{
public:
    static int somethingStatic()
    {
        //...
    }

    void someMember()
    {
        //...
    }
};

int main()
{
    std::vector<Interface*> vec;
    SpecificImpl instance;

    //...

    vec.push_back(&instance);

    //...

    for(auto* inst : vec) {
        inst->doSomething();
    }

    //...
}

【讨论】:

  • 运行时成本是否与仅使用纯虚函数相同?
  • 是的,因为模板完全没有运行时开销。
  • 那么与仅使用纯虚函数相比,看这段代码 CRTP 不会给我太多好处?我有同样的性能损失?
  • 抱歉,误解了您的问题。如果您愿意,您可以使顶级虚函数调用(在我的示例中为main 函数中的inst-&gt;doSomething())是唯一承载虚调用开销的函数。由于其模板性质,调度到其下的特定实例的细节(如上面的static_cast&lt;T*&gt;(this)-&gt;someMember())不会招致任何此类惩罚。这绝对比仅抽象方法更有效,后者通过受保护的覆盖虚拟方法调用特定的实例代码。
  • 因此您拥有两全其美:低级实现的模板效率,但仍然具有顶层虚拟多态性的优势,例如允许客户端保留所有多态性实例在一个容器中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多