今天遇到一个挺有趣的例子来说明虚函数的覆盖问题,代码如下:
#include<iostream>
using namespace std;
struct B{
virtual void f()const{cout<<"B::f ";}
void g()const{cout<<"B::g ";}
};
struct D:B{
void f()const{cout<<"D::f ";} //覆盖B::f
void g(){cout<<"D::g ";}
};
struct DD:D{
void f(){cout<<"DD::f ";}
void g()const{cout<<"DD::g ";}
};
void call(const B&b){
b.f();
b.g();
}
int main(){
B b;
D d;
DD dd;
call(b);
call(d);
call(dd);
b.f();
b.g();
d.f();
d.g();
dd.f();
dd.g();
}
编译后输出为:
当你理解了为什么是这样的输出结果后,你就会清楚继承和虚函数机制了。
我个人的理解如下,首先类层次关系如图:
b.f() , b.g() , d.f() , d.g() , dd.f() , dd.g() 的结果很好理解。call(b)也无需解释。
调用call(d)时,因为D类中f()为虚函数覆盖了B类的f(),所以call(d)下d.f()的运行结果为:D::f,相当于执行D类的私有函数。
而call(d)下d.g()的运行结果为B::g。
调用call(dd)时,因为DD类中f()函数与D类的不同,不覆盖,所以call(dd)下dd.f()的运行结果为:D::f,相当于执行D类中的f()函数。而call(dd)下dd.g()的运行结果为B::g,因为DD类中的g()函数与D类中不同,所以再往上回溯,运行结果为B::g。