C++的继承机制图解

最近一直想用一张图去总结C++的继承机制。但是很快就发现,C++的继承机制比自己想象中要复杂得多,根本不可能用一张图就是解释得清楚。不过万事并不是一定要得到结果才算成功,想要总结的念头本身就让自己无形中有了对继承机制有了更深的理解。也尝试着用一张图去解释单继承中public,protected, private继承的特点,以及父类和子类中虚函数,构造函数和析构函数的关系。

图中的点线线框(比如成员函数,构造函数和析构函数)表示不占有类的内存,箭头只是表示逻辑相连。 我们从上面开始说。 当一个基类的指针或者引用(引用机制其实和指针一样)被赋予了派生类的时候,其指向的仍然是基类的隐含对象的首地址。 如果基类中没有虚函数,则首地址指向的是基类的第一个成员变量。因此当用基类去调用成员函数的时候,调用的都是基类自己的成员函数。 而如果基类中虚函数,那么首地址就会存在一个vptr指针,指向一个vtable,vtable中存放着所有虚函数的在代码库(代码库是专门用来存放函数的)中的地址,而在继承过程中,vptr会被更新,指向派生类自己的vtable,于是虽然指针指向的时基类的首地址,但此时,这个首地址指的是派生类虚函数的vtable,所以用基类指针调用方法的时候,就会调用到子类的成员函数(当然得是虚函数)。 关于公有,保护和私有继承,就比较好记,记住这么一个式子就可以:min(原来访问属性,继承属性),这里,我们假设public>protected>private. 如果是私有继承,那么基类中所有的成员的最高访问属性就不能超过私有。而如果新的访问属性大于私有,则会在派生类中开放一个访问渠道,派生类中得成员函数就可以访问基类的成员,而如果大于保护属性,则会在类外开放一个渠道。 对于继承而言,比如公有继承,基类中所有的公有变量都可以看做是派生类的共有变量,但是这幅图想说明的是,这些变量本质上还是在基类里面,只是在开放给了派生类,于是才等价于派生类自己的成员。 另外,构造函数和析构函数都是不可以被继承的。也就是说,派生类有自己的构造函数和析构函数,基类也有自己的构造函数和析构函数,但是都是相互独立没有联系的。我们之所以要经常把析构函数都赋予virtual的属性,也是由我们最初的基类指针引发的。因为基类指针虽然表面指向了派生类,但是本质上是指向了派生类中的隐含基类对象,所以你在在使用完这个基类指针的时候,用delete语句只能调用基类的析构函数,这个时候基类这个隐含对象没了,但是派生类的其他部分并没有被释放!这就是非常危险的内存泄露!所以用了虚析构函数之后,就可以调用派生类的析构函数,当然如果你调用派生类的虚构函数的时候,其内在的执行顺序是先执行基类的析构函数,再去释放派生中新增的部分,这样就不会造成内存的泄露。 基本上这幅图就包含了这些知识点。当然C++的继承机制,远远比这个要复杂,这里没有考虑到静态成员变量,也没有考虑到多重继承,不过学习总是循序渐进的,相信用图形去思考问题,肯定能让理解更为深刻。 如果这中间有什么写的不对,欢迎指正,谢谢!

打赏还是要有的,万一有人打赏呢!