问题:
写出下面程序的运行结果:
#include <iostream>
using std::cout;
using std::endl;
class A
{
public:
void nonVirtualFun()
{
cout<<"1"<<endl;
}
virtual void virtualFun()
{
cout<<"2"<<endl;
}
virtual ~A(){}
};
class B:public A
{
public:
void nonVirtualFun()
{
cout<<"3"<<endl;
}
void virtualFun()
{
cout<<"4"<<endl;
}
};
int main()
{
A a;
B b;
A *pa=&a;
pa->nonVirtualFun();
pa->virtualFun();
pa=&b;
pa->nonVirtualFun();
pa->virtualFun();
B *pb=(B*)(&a);
pb->nonVirtualFun();
pb->virtualFun();
return 0;
}
如果你的答案是1,2,1,4,3,2
那么恭喜你答对了。下面来分析一下内存与虚函数机制。
首先要明确的是:
对于类的非虚函数,那么编译之后与全局函数没有什么区别,编译器会自动给该函数加一个this参数,用于指明是哪个对象调用的该函数。
对于类的虚函数,都是通过虚函数指针(vptr-->vtbl)来访问的。
所以编译之后的类A和类B的内存模型如下:
这也可以解释大多数人认为C++比C慢的原因:对于虚函数的访问需要简直通过指针,如果你不用虚函数,C++并不比C慢。
从下面这段代码开始分析:
pa=&b;
pa->nonVirtualFun();
pa->virtualFun();
访问虚函数时通过虚函数表(vtbl),由于vptr指向的是子类的虚函数表,所以自然而然的访问了子类B::virtualFun(),即实现了运行期多态。
再来分析最后一段代码:
B *pb=(B*)(&a);
pb->nonVirtualFun();
pb->virtualFun();