基类存储空间是派生类对象存储空间的一部分,计算派生类的存储空间要先计算基类的,从先调用基类构造函数在调用派生类构造函数这一点可以看出。但基类和派生类的静态数据成员是脱离对象独立存在的,其存储单元不属于任何对象的一部分,但对于任何对象都共享,相当于一个全局变量,实际上编译程序分配内存区的时候也将其分配在全局区。局部类不允许定义静态数据成员,会产生矛盾。
对于虚函数,当一个类定义了虚函数则会生成一个属于该类的虚函数地址表,构造对象时,构造函数会先将虚函数入口地址表的首址放到对象的起始单元。如果是实继承,派生类先将基类的虚函数地址表首址放入起始单元,但在之后又会将自己派生类的虚函数入口地址表的首址放入起始单元,所以一共只占了一个虚表指针大小的空间。如果是虚继承,由于虚基类的构造函数要尽可能早执行,析构函数尽可能晚执行,虚基类有自己的存储空间,派生类还要有一个指向基类的指针,所以要计算基类和派生类各自的虚表入口首址和指向基类的指针大小(偏移)。一般指向虚基类的指针放在起始单元,虚基类存储空间放在派生类的尾部,都是按构造顺序排列的。
对于多继承派生,每个基类都有自己的存储结构,如果派生类继承的第一个类为基类,且该基类定义了虚函数地址表,则派生类会共用该表首址占用的存储单元,否则派生类在处理完所有基类和虚基类后根据自己有无虚函数确定是否为该虚表首址分配存储单元。
另外看到一点:在具有基类和虚基类的多继承派生类中,如果虚基类和基类的成员同名,根据面向对象的作用域规则,优先访问基类成员。