一提起C++的多态,很自然就想起了函数重载和虚函数的实现。函数重载是在编译时实现的一种多态,而运行时的一种多态可以通过虚函数来实现。具体一点的例子就是通过基类指针指向其子类的实例,然后来调用实际子类的成员函数。既然说到虚函数,那么虚函数表必然要提一下;我想用例子来加深一下对这方面的认识:
#include<iostream>
using namespace std;
class Base
{
public:
Base(){}
virtual ~Base(){}
int b_num;
virtual void func1(){cout<<"func1: In base~"<<endl;}
virtual void func2(){cout<<"func2: In base~"<<endl;}
};
class Derive: public Base
{
public:
Derive(){}
~Derive(){}
int d_num;
void func1(){cout<<"func1: In derive~"<<endl;}
};
int main()
{
cout<<sizeof(Base)<<" "<<sizeof(Derive)<<endl;
Derive d;
Base* b=&d;
b->func1();
b->func2();
return 0;
}
输出:
8 12
func1: In derive~
func2: In base~
对于类的内存组织的描述
(1)类Base的内存组织类似于:
VPTR是一个虚函数表指针,指向该类的虚函数表。由上图可以看出Base类的内存空间存放了该指针以及一个整型的数据成员,因此该类的长度为8.
(2)类Derive的内存组织类似于:
由上图可知,在派生类中VPTR指向了该类的一个虚函数表,这个是从基类的虚函数表中来的;由于派生类Derive中覆盖了基类的func1虚函数,那么新的虚函数表也做了相应的覆盖。
在派生类的内存空间中,存储了虚函数表指针VPTR,基类的数据成员b_num,还有自身的数据成员d_num,因此sizeof(Derive)的长度为12.
由于func1的函数在派生类中被覆盖,通过基类指针指向的派生类的虚函数表中的是Derive::func1();而func2()函数没有被覆盖,因此指向的还是派生类中虚表的Base::func2().