什么是C++对象模型?


引用《深度探索C++对象模型》中的两个概念:

  1. 语言中直接支持面向对象程序设计的部分

  2. 对各种支持的底层实现机制

In my opinion 对象模型是对象在存储空间上的空间比时间更优,并对C++面向对象的技术加以支持,如虚指针虚表指针支持多态性。什么是多态?

●多态

C++中虚函数的作用主要是为了实现多态机制。多态,是指在继承层次中,父类的指针可以具有多种形态——当他指向某个子类对象时,通过它能调用到子类的函数,而非父类的函数。简单滴讲,当使用基类的指针或引用重写的虚函数时,当使用父类调用的就是父类的虚函数,指向子类就是子类的虚函数。

#include<iostream>
using namespace std;
class Person
{
public:
    virtual void BuyTicket()
    {
        cout<<"买票"<<endl;
    }
};
class Student
{
public:
    virtual void BuyTicket()
    {
        cout<<"买票半价"<<endl;
    }
};
void Fun(Person& P)
{
    P.BuyTicket();
}
void Test()
{
    Person P;
    Student S;
    Fun(P);
    Fun(S);
}

虚函数表解析

含有虚函数或其父类含有虚函数的类,编译器都会为其添加一个虚函数表vptr,(先了解虚函数表,有助于C++对象模型的理解)

继承下的C++对象模型。分析C++对象在下面情形中的内存布局:

单继承:子类单一继承自父类,分析了子类重写父类函数,子类定义了新的虚函数情况下子类对象的内存布局。

多继承:子类继承于多个父类,分析了子类重写父类函数,子类定义了新的虚函数情况下子类对象的内存布局,同时分析了虚继承下的菱形继承。

虚继承:分析了单一继承体系下的虚继承、多重基层下的虚继承、重复继承下的虚继承。

●虚表

class Base
{
public:
    Base(int i)
        :basel(i)
    {}
    vitual void print(void)
    {
        cout<<"调用了虚函数的Base::Print()";
    }
    virtual stel()
    {
        cout<<"调用了虚函数的Base::stel()";
    }
    virtual ~Base()
    {}
private:
    int basel
};

 wKiom1cxr-bDb0YUAABXOhbqqRM544.jpg

当一个类本身定义了虚函数,或其父类有虚函数时,为了支持多态机制,编译器将为该类添加一个虚函数表指针,虚函数指针一般都放在对象内存布局的第一个位置上,这是因为保证在多层继承或多重继承下能最高效率地取到虚函数表。

 当vptr位于对象内存最前面时,对象的地址即为虚函数指针地址。

每个类对象都拥有一个虚表指针, 由编译器为其生成。虚表指针的设定与重置皆由类的复制控制(也是构造函数,析构函数,赋值操作符)来完成。vptr的位置为编译器决定,传统上它被放在所有显示声明的成员之后, 不过现在许多编译器把vptr放在一个类对象的最前端。

●菱形继承

菱形继承也称钻石继承或重复继承,它指的是基类被某个派生类简单重复继承了多次,

wKioL1cx7jCRUY7sAAEkLLCdxLw275.jpg

 ●虚拟继承

菱形虚拟继承下,派生类对象又有不同的构成了,在D类的内存构成上,有以下几点:

在D类对象的内存中,基类出现的顺序是:先是B1类(最左父类),然后B2类(次左父类),最后是B类(虚祖父类)

菱形继承下的对象模型是:

wKioL1cx8JDzzpzeAAUIapr-RRE447.jpg