c++ - 将继承的 CRTP 实现注入(inject)继承的接口(interface)类

标签 c++ interface c++14 crtp vtable

我想在不产生额外的 v-table 成本的情况下摆脱重复的代码。

  • B是一个接口(interface)类:它不能是虚拟的
  • D1D2是 B 的具体类。
    • 部分相同:显示为std::cout<<"same"在 mcve 中。
    • 有些部分不同:显示为different1()different2() .

这是代码。它工作正常。 ( Demo )

class B{//can't be template
    public: virtual void show()=0;
};
class D1 : public B{
    public: bool different1(){return true;}
    public: virtual void show(){ 
        if( different1() )
            std::cout<<"same";   //duplicate
    }
};
class D2 : public B{
    public: bool different2(){return true;}
    public: virtual void show(){ 
        if( different2() )
            std::cout<<"same";   //duplicate
    }
};
int main(){
    D1 d;
    B* b=&d;
    b->show();  //1 v-table look up : OK!
}

我糟糕的解决方案(1/2)

将重复代码移至基类( Demo ):-

class B{//can't be template
    public: virtual void show(){
        if( differentX() )
            std::cout<<"same";   //duplicate
    }
    public: virtual bool differentX() = 0;
};
class D1 : public B{
    public: bool differentX(){return true;}
};
class D2 : public B{
    public: bool differentX(){return true;}
};

问题是 b->show()将招致 2 个 v 表查找。 (?)

我知道“过早的优化是邪恶的”,但我想听听是否有可能将 v-table 成本降低到 1。(在找借口并使用这种方法之前)

我糟糕的解决方案 (2/2)

使用 CRTP ( demo )

class B{//can't be template
    public: virtual void show()=0;
};
template<class T>class C{  //
    public: bool differentX(){
        return static_cast<T*>(this)->differentImpl()   ;
    }
    public: void show(){
        differentX();
        std::cout<<"same"; 
    }
};
class D1 : public B, public C<D1>{
    public: bool differentImpl(){return true;}
};
class D2 : public B, public C<D2>{
    public: bool differentImpl(){return true;}
};

但是,它不再符合要求,因为 D1不再是具体类。

如何解决?我是 CRTP 的新手。

最佳答案

这个解决方案怎么样?

C 实现了 B 的 show 方法并提供了 show 的通用实现,它依赖于提供不同实现的模板参数 T。

D1和D2继承自C,以自己为模板参数。

http://coliru.stacked-crooked.com/a/34e8a727e81e19f7

#include <iostream>
class B {//can't be template
    public: virtual void show() = 0;
};

template<class T>
class C : public B {
public:
    void show() override {
        if (Impl().different()) {
            std::cout << "same"; 
        }
    }
private:
    T& Impl() {
        return *static_cast<T*>(this);
    }
};

class D1 : public C<D1> {
    public: bool different() { return true; }
};
class D2 : public C<D2> {
    public: bool different() { return true; }
};

int main() {
    D1 d;
    B* b = &d;
    b->show();  
}

关于c++ - 将继承的 CRTP 实现注入(inject)继承的接口(interface)类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45612144/

相关文章:

c++ - 在char数组(流)c++中查找和替换字符串的函数

c++ - 当我的程序不在焦点时,不获取 GetAsyncKeyState。玩游戏时不工作

interface - 如何使用相同的方法签名实现两个不同的接口(interface)

c++ - 成对函数评估算法(C++、STL)

c++ - Clang 不能与 std::experimental::optional 一起正常工作

c++ - 对于 MySQL 和 c++ 来说,没有文件(即内存中)的 “Load DATA” 是否可行

Raspberry Pi 1 B 上的 c++ bass 和 rapidXml

Java - 用于重复 sql 任务的设计模式

ios - 工具栏上的 BarButtonItem

c++ - 如果创建支持返回可变类型列表的通用模板 API,我应该使用 std::tuple 还是其他?