【发布时间】:2017-08-10 11:13:36
【问题描述】:
我想摆脱重复代码而不产生额外的 v-table 成本。
-
B是一个接口类:它不能是虚拟的 -
D1和D2是 B 的具体类。- 它们的某些部分是相同的:在 mcve 中显示为
std::cout<<"same"。 - 有些部分不同:显示为
different1()和different2()。
- 它们的某些部分是相同的:在 mcve 中显示为
这里是代码。它工作正常。 (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-table 查找。 (?)
我知道“过早的优化是邪恶的”,但我想知道是否可以将 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 新手。
【问题讨论】:
-
解决方案 1 有什么问题?
-
@BЈовић 我相信它需要 2 个 vtable 查找:
show和differentX。 -
显然,要使解决方案 2 起作用,假设您要重用显示代码,您的 C 类必须从 B 派生。但是,解决方案 1 通常会更好,但它确实取决于实际代码和用法......
-
第一次调用的开销更大,第二次调用的开销不大,因为“this”被加载到缓存中。应该只是间接函数调用。还是我错了?
-
@Phil1970 听起来不错....我会对此进行更多调查。谢谢。
标签: c++ interface c++14 crtp vtable