将实现从继承的 CRTP 注入到继承的接口类
Injecting implementation from inherited CRTP to inherited interface class
我想在不产生额外对等表成本的情况下摆脱重复的代码。
B
是一个接口类:它不能是虚拟的D1
和D2
是B的具体类。- 它们的某些部分是相同的:在mcve中显示为
std::cout<<"same"
。 - 有些部分是不同的:显示为
different1()
和different2()
。
- 它们的某些部分是相同的:在mcve中显示为
这是代码。 它工作正常。 (演示(
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(
将重复的代码移动到基类(演示(:-
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 次对表查找。 (?)
我知道"过早优化是邪恶的",但我想听听是否有可能将逆向表成本降低到 1。(在找借口并使用这种方法之前(
我糟糕的解决方案 (2/2(
使用 CRTP(演示(
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();
}
解决方案 3 :将重复的代码放在函数中。像这样:
class B{//can't be template
public: virtual void show()=0;
public: void same(){
std::cout<<"same"; //no duplicate
}
};
class D1 : public B{
public: bool different1(){return true;}
public: virtual void show(){
if( different1() )
same();
}
};
class D2 : public B{
public: bool different2(){return true;}
public: virtual void show(){
if( different2() )
same();
}
};
int main(){
D1 d;
B* b=&d;
b->show(); //1 v-table look up : OK!
}
正如我在评论中所说,您可以创建一个具有通用功能的函数:
void ShowFuncX( B& b )
{
if ( b.differentX() )
{
std::cout<<"same";
}
}
然后在派生中:
class D1 : public B{
public: bool different1(){return true;}
public: virtual void show(){
ShowFuncX( *this );
}
};
class D2 : public B{
public: bool different2(){return true;}
public: virtual void show(){
ShowFuncX( *this );
}
};
另请参阅"为需要重复两次的任何内容编写函数是否始终是最佳做法?
相关文章:
- Qt Quick - 如何在 qml 接口中使用继承自 QQuickPaintedItem 的 c++ 类?
- C++接口继承不同的参数方法
- c++ com 如何继承 IUIAutomationPropertyChangedEventHandler 接口
- C++ 使用接口和默认实现继承
- C++ 通过接口使用从其他几个类继承的类
- 如何在C++中访问 DirectWrite 继承的接口?
- 接口的钻石继承(C++)
- 将实现从继承的 CRTP 注入到继承的接口类
- C++:继承自基类和具有公共基接口的多个接口
- 接口实现和私有继承之间的交互
- 替代与djinni的接口继承
- C++ 接口类继承自具体类是否合理
- C++接口、继承、多态性
- 继承接口实现
- 继承C++接口和 LSP 冲突
- 为什么C++不允许基类实现派生类的继承接口?
- 物理引擎的继承/接口决策
- 使用继承接口的类的子类方法
- 我的类如何继承接口和QObject
- 从基础对象继承接口是一种好的做法吗