virtual
方法是polymorphism的C ++实现的一部分。除了避免与RTTI ** 和方法查找相关的开销之外,有没有令人信服的理由忽略virtual
?
假设virtual
可以随时添加到基类中,重新定义非virtual
方法的目的是什么?
**它是否可以在现代CPU上测量与此问题无关。
答案 0 :(得分:2)
嗯,没有理由重新定义一个非虚拟的函数。事实上,我建议不要使用它,因为看起来完全相同的对象上的相同函数调用可能会根据所使用的指针/引用的静态类型而有所不同。
覆盖虚拟成员函数允许您专门化派生类型的行为。 重载非虚拟成员函数将改为提供另一种行为,在这种行为中,对于不经意的读者来说,哪些函数/行为将被执行可能并不明显。
答案 1 :(得分:2)
一种可能的用途是实现CRTP框架,其中定义了默认版本的函数:
#include <iostream>
//This could be any higher-order function.
template<typename T>
class CallFiveTimes {
protected:
void docalls() const {
for(int i(0); i != 5; ++i) static_cast<T const*>(this)->callme();
}
//Default implementation. If a lot
//of different functionality were required of `T`
//then defaults could make `T` easier to write.
void callme() const {
std::cout << "Default implementation.\n";
}
};
class Client : CallFiveTimes<Client> {
public:
void useFramework() {
docalls();
}
private:
friend struct CallFiveTimes<Client>;
//This redefinition will be used.
void callme() const {
std::cout << "Client implementation.\n";
}
};
class LazyClient : CallFiveTimes<LazyClient> {
public:
void useFramework() {
docalls();
}
friend struct CallFiveTimes<LazyClient>;
};
int main() {
Client c;
c.useFramework(); //prints "Client Implementation" five times
LazyClient lc;
lc.useFramework(); //prints "Default Implementation" five times
}
我从未在实践中看到过这种情况,但在某些情况下可能值得考虑。