在 C++ 中,有没有办法让“抽象”基类方法(即,从基类声明和调用,但在子类中实现)而不将方法声明为virtual
?
当然,这个问题只适用于不需要多态性的情况(从未使用过的基类型的指针/引用)。考虑以下:
#define NO_OPT asm volatile (""); // to prevent some compiler optimization
template<typename DerivedType>
void doSomething(DerivedType& d) { d.foo(); }
namespace test1 {
struct Base {
inline void foo()
{
// ... do common stuff pre-call ...
foo_impl();
// ... do common stuff post-call ...
}
virtual void foo_impl() = 0; // the abstract method
};
struct D1 : public Base { virtual void foo_impl() final { NO_OPT } };
struct D2 : public Base { virtual void foo_impl() final { NO_OPT } };
// Then the usage of D1, D2, ..., DN, could be as follows:
void go() {
D1 d1; doSomething(d1);
D2 d2; doSomething(d2);
for ( long i=0; i < 5000000000; i++ ) {
// this loop takes [9] seconds
doSomething(d2);
}
}
}
请注意,在这种情况下不需要多态性,并且编译器有很多优化机会。
g++
但是,我在最新的(4.8.2) 和clang
(3.4)中对这段代码进行了基准测试,并-O3
启用了优化,包括链接时间 (LTO),它比以下替代实现慢得多(使用模板而不是虚拟方法):
namespace test2 {
template<typename DerivedType>
struct Base : public DerivedType // inheritance in reverse
{
inline void foo()
{
// ... do common stuff pre-call ...
DerivedType::foo_impl();
// ... do common stuff post-call ...
}
};
struct D1 { void foo_impl() { NO_OPT } };
struct D2 { void foo_impl() { NO_OPT } };
void go() {
Base<D1> d1; doSomething(d1);
Base<D2> d2; doSomething(d2);
for ( long i=0; i < 5000000000; i++ ) {
// this loop takes [3] seconds
doSomething(d2);
}
}
}
g++
并且clang
非常一致,每次编译优化代码需要 9 秒来执行test1
循环,但只需要 3 秒来执行test2
循环。因此,即使test1
逻辑不需要动态调度,因为所有调用都应该能够在编译时解决,但它仍然明显慢得多。
所以重申我的问题:当不需要多态性时,有没有办法使用方便的直接类继承(如 in )来实现这种“抽象方法”行为test1
,但没有虚函数的性能损失(如在test2
)?