深度探索C++对象模型 读书笔记


 最近在看《深度探索C++对象模型》这本书,作者是Lippman 计算机界的巨人,我个人认为从第四章开始阅读是最佳的。注:为了方便查看笔记的标题为图书的标题,内容为本人对其的理解以及一些心得。

The Semantics of Function

       C++中函数无非就是类的成员函数,普通函数,然后加上各种关键字修饰,例如Static   inline  const  virtual。常见的操作包括重载,重写等,更深入的使用包括函数指针,模板函数,以及在运行时,函数作用域内相关参数的初始化之类,仅仅只是知其然而不知其所以然是不够的,必须得弄清楚这些操作的底层原理,才能更好的理解以及应用。

 4.1 Member的各种调用方式

       Lippman概述了类中  静态与非静态成员函数以及虚成员函数,因为编译器对它们的操作都不同。

以下是我的理解:

Nonstatic Member Functions 

      任何非静态成员函数在编译器内部都会被转化为 void 返回类型的函数,而且此函数带有编译器创造的两个形参,一个是带有const修饰地址的类的this指针,另一个是原本类型的引用作为返回值,这样所有不同的非静态成员函数经过转化后结构都变得一样了?甚至和非静态非成员函数一样,这实在太巧妙了,这令其拥有非成员函数一样的效率。

Virtual Member Functions 

      虚成员函数...通过指向派生类的基类指针调用虚成员函数可以达到在运行时动态的调用,其原理在VS编译器中是对每个有虚成员函数的类以及其派生类中添加一个虚函数指针指向其对应的虚函数表,当然在某些复杂的虚继承中可能会拥有多少虚函数指针以及其对应的多个虚函数表,复杂且开销很大并且难以琢磨,幸运的是工作中很少用到。那如果是一个经由已明确声明的对象去调用其虚成员函数呢?这时会压制虚拟机制,等同于调用一个普通的成员函数。

 Static Member Functions

      静态成员函数比起非静态成员函数,少了编译器创造的带有const修饰地址的类的this指针,这意味着你的静态成员函数中将无法调用类域中其他非静态的成员变量以及函数,因为没了this指针。比起一般的静态函数,多了一个类域,需要加上类域或者指向该类的指针(即便是无效指针)就能调用,同时静态成员函数也不能被声明为const、volatile、或者virtual,为什么?Lippman一语带过,全是因为其没有this指针!!!所以可以推断const、volatile、或者virtual都需要this指针或者是修饰this指针指向的值。(volatile修饰 精确地说就是,编译器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份)

 4.2 Virtual  Member Functions

       这一章,Lippman详细剖析了虚函数模型。虚函数应用场景有单一继承、多重继承和虚拟继承..

      要想彻底研究虚函数机制,首先得了解虚函数是如何在执行期进行判断和调用的。首先肯定是通过指针指向地址进行调用的,其次指针可能会含有可以判断运行时的对象类型和指向函数实例的地址吗,细想一下这些虚函数地址要是存放在类的内存模型中可以实现多态吗?可以实现,但是需要一个结构体去存放有关虚函数的各种信息,在运行时进行大量判断最后才能正确调用目标函数。为了进行判断,Lippman引出了RTTI的概念,即运行时类型检查,C++要想在运行时去获取对象的类型信息只能通过RTTI机制,不像JAVA可以通过反射等操作获取运行时的对象信息。

        RTTI提供两个操作符  typeid:返回指针和引用所指的实际类型;

                                          dynamic_cast操作符,将基类类型的指针或引用安全地转换为其派生类类型的指针或引用。

       最后的解决方案是,通过创建虚函数表的形式将类中的虚函数的地址(函数的地址在编译期就已经全部确定)存放到拥有对应特定的虚函数表的索引值下的空间。编译器会在多态类中生成两个成员一个虚函数指针和一个可以表示class类型的字符串的值。