模板作为C++中虚拟功能的替代品
Templates as an alternative to virtual functions in C++
>我在基类中定义了一个昂贵的函数,它依赖于其派生类的低级信息:
class BaseClass{
...
// Defined in derived class
virtual int low_level(int)=0;
// Expensive function depending on the pure virtual function
void myExpensiveFunction(){
for(...){
for(...){
for(...){
... = low_level(...);
...
}
}
}
}
};
class DerivedClass : public BaseClass{
// A very cheap operation that can be inlined:
inline virtual int low_level(int i){
return a[i];
}
// Calling the base class function
void test(){
myExpensiveFunction();
}
};
如果我理解正确,低级函数是虚拟的这一事实会阻止它在上面的代码中内联。现在,我正在考虑一种解决此问题的方法,并想到了以下解决方案,其中我将指向派生类成员函数的指针作为模板参数传递:
class BaseClass{
...
// The function is now templated by the derived function:
template<typename D, int (D::*low_level)(int)>
void myExpensiveFunction(){
for(...){
for(...){
for(...){
... = static_cast<D*>(this)->low_level(...);
...
}
}
}
}
};
class DerivedClass : public BaseClass{
// A very cheap operation that can be inlined:
inline int low_level(int i){
return a[i];
}
// Calling the base class function
void test(){
myExpensiveFunction<DerivedClass,&DerivedClass::low_level>();
}
};
这种策略有意义吗?我想当昂贵的基类函数在派生类中扩展时,低级操作将被内联。
我测试了实现它,它可以编译和工作,但我没有看到任何明显的性能差异。
亲切问候乔尔
使用指向基类的成员指针将要调用的函数传递给基类并不比使用虚函数真正改善。事实上,我预计这会让情况变得更糟。另一种方法是使用带有inline
函数调用运算符的函数对象并调用 this。"正常"的方法是反转类层次结构并使用奇怪的重复模板模式:这个想法是创建一个模板,该模板将派生自其模板参数。模板参数应提供自定义点,例如函数low_level
。
根据情况,您还可以尝试完全避免继承,而是执行以下操作:
template<typename LL>
class HighLevel {
LL lowLevel;
public:
HighLevel(LL const &ll) : lowLevel(ll) { }
void myExpensiveFunction() {
for(...) {
for(...) {
for(...) {
... = lowLevel.low_level(...);
...
}
}
}
}
};
class LowLevel {
public:
inline int low_level(int i) { // note: not virtual
return a[i];
}
};
用于:
HighLevel<LowLevel> hl;
hl.myExpensiveFunction();
如果您不希望不同类型的HighLevel<...>
对象漂浮,则可以从抽象的非模板class HighLevelBase
中派生所有这些对象,该该公开在模板中实现的virtual void myExpensiveFunction() = 0
。
这是否对你的情况有意义,如果没有更多信息,我无法判断,但我发现C++通常提供比继承更好的工具来解决特定问题。
相关文章:
- 如何在C++中获得"静态纯虚拟"功能?
- std::is_trivially_copyable_v 关于虚拟功能
- 隐藏重载虚拟功能的模板化访客:SFINAE 在使用?
- 为什么我无法覆盖虚拟功能?
- 虚拟功能不起作用
- 如果在创建对象时创建了 VPTR,那么为什么具有虚拟功能的类的大小在 32 位系统上为 4,在 64 位机器上为 8
- 虚拟功能如何影响static_cast?
- __declspec(属性)和虚拟功能
- 实现来自第三方类的虚拟功能
- 消除未使用的虚拟功能
- 为什么虚拟继承即使不涉及虚拟功能也需要 vtable?
- C 虚拟功能的输出
- 抽象类 A 由类 C 继承"through"类 B "intermediary"。如何声明虚拟功能?
- 虚拟功能是否不太可能导致堆栈溢出
- 使用继承和虚拟功能应用五个规则
- 两个派生类(十六进制 二进制)的虚拟功能
- 虚拟功能编译器优化C
- 虚拟功能指针指向派生类中的函数
- 隐藏的过载虚拟功能OSX QT4
- 使用虚拟功能在C 中进行猜测