无继承的C++对象模型
我们先定义一个基类。
class Base
{
public:
Base() {};
virtual ~Base(){}
void no_static_member_function(){ }
static void static_member_function(){}
virtual void virtual_member_function(){ }
private:
int no_static_member_data;
static int static_member_data;
};
这是一个典型的非继承的C++类,它的对象模型如下:
有继承的C++对象模型
Drived为Base的派生类
class Drived1:public Base
{
public:
Drived1(){}
virtual ~Drived1(){}
virtual void virtual_member_function(){ }
virtual void virtual_member_function2(){ }
private:
int m1;
}
我们来看一下它的对象模型:
在C++对象模型中,对于一般继承(这个一般是相对于虚拟继承而言),若子类重写(overwrite)了父类的虚函数,则子类虚函数将覆盖虚表中对应的父类虚函数(注意子类与父类拥有各自的一个虚函数表);若子类并无overwrite父类虚函数,而是声明了自己新的虚函数,则该虚函数地址将扩充到虚函数表最后(在vs中无法通过监视看到扩充的结果,不过我们通过取地址的方法可以做到,子类新的虚函数确实在父类子物体的虚函数表末端)。而对于虚继承,若子类overwrite父类虚函数,同样地将覆盖父类子物体中的虚函数表对应位置,而若子类声明了自己新的虚函数,则编译器将为子类增加一个新的虚表指针vptr,这与一般继承不同,在后面再讨论。
多继承的C++对象模型
Drived2同时继承Base和Base1
class Base1
{
public:
Base1() {};
virtual ~Base1(){}
void no_static_member_function(){ }
static void static_member_function(){}
virtual void virtual_member_function(){ }
private:
int no_static_member_data1;
static int static_member_data;
};
class Drived2:public Base,public Base1
{
public:
Drived2(){}
virtual ~Drived2(){}
virtual void virtual_member_function(){ }
private:
int md2;
};
我们来看一下它的对象模型:
此情况下由于静态数据成员为私有,故在派生类中不会有不明确的情况,但静态成员函数是public的,此时以派生类方式调用会产生定义不明确的错误。
对于基类的虚表都会被派生类overwrite覆盖。
下一节讨论虚继承的C++对象模型