我希望摆脱重复的代码,而不会产生额外的v-table成本。
B
是一个接口类:它不能是虚拟的D1
和D2
是B的具体类。
std::cout<<"same"
。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!
}
将重复的代码移至基类( 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.(在借口并使用此方法之前)
使用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的新手。
答案 0 :(得分:2)
如何解决这个问题?
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();
}
答案 1 :(得分:1)
解决方案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!
}
答案 2 :(得分:1)
正如我在评论中所说,你可以创建一个具有共同功能的功能:
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 );
}
};
另请参阅“Is it always a best practice to write a function for anything that needs to repeat twice?”