电影: 新少林寺naked 函数调用C++虚函数的实现细节、虚析构函数 汇编解析

C++重要学习点

拒绝使用基类成员函数指针进行任务分派
潘凯:C 对象布局及多态实现的探索(六)...
潘凯:C 对象布局及多态实现的探索(十)...
1.继承、多态继承特性:(1)若类中有虚函数,对象中从低地址到高地址存放的内容为:先存放虚函数表指针,再存放自基类继承的成员变量,最后存放自身的成员变量;(2)虚函数表中从低地址到高地址存放的内容为:先存放自基类继承的虚函数的指针,再存放自身的虚函数的指针。(注意:如果派生类覆盖了基类的虚函数,则虚函数表中先存放的是被覆盖后的虚函数的指针,否则先存放的是原始的(即基类的)虚函数的指针)

2.1时间:在通过继承类对象访问虚基类对象中的成员(包括数据成员和函数成员)时,都必须通过某种间接引用来完成,这样会增加引用寻址时间(就和虚函数一样),其实就是调整this指针以指向虚基类对象,只不过这个调整是运行时间接完成的。

2.2空间:由于共享所以不必要在对象内存中保存多份虚基类子对象的拷贝,这样较之多继承节省空间。虚拟继承与普通继承不同的是,虚拟继承可以防止出现diamond继承时,一个派生类中同时出现了两个基类的子对象。也就是说,为了保证这一点,在虚拟继承情况下,基类子对象的布局是不同于普通继承的。因此,它需要多出一个指向基类子对象的指针。

3.笔试,面试中常考的C++虚拟继承的知识点

第一种情况:         第二种情况:          第三种情况            第四种情况:class a           class a            class a              class a{              {                {                 { virtual void func();      virtual void func();       virtual void func();        virtual void func();};              };                  char x;              char x;class b:publicvirtuala   class b :public a        };                };{              {                class b:publicvirtuala      class b:public a virtual void foo();       virtual void foo();     {                 {};              };                  virtual void foo();        virtual void foo();                               };                };

如果对这四种情况分别求sizeof(a), sizeof(b)。结果是什么样的呢?下面是输出结果:(在vc6.0中运行)第一种:4,12第二种:4,4第三种:8,16第四种:8,8

想想这是为什么呢?

因为每个存在虚函数的类都要有一个4字节的指针指向自己的虚函数表,所以每种情况的类a所占的字节数应该是没有什么问题的,那么类b的字节数怎么算呢?看“第一种”和“第三种”情况采用的是虚继承,那么这时候就要有这样的一个指针vptr_b_a,这个指针叫虚类指针,也是四个字节;还要包括类a的字节数,所以类b的字节数就求出来了。而“第二种”和“第四种”情况则不包括vptr_b_a这个指针,这回应该木有问题了吧。

4.c++重载、覆盖、隐藏的区别和执行方式

既然说到了继承的问题,那么不妨讨论一下经常提到的重载,覆盖和隐藏4.1成员函数被重载的特征(1)相同的范围(在同一个类中);(2)函数名字相同;(3)参数不同;(4)virtual 关键字可有可无。4.2“覆盖”是指派生类函数覆盖基类函数,特征是:(1)不同的范围(分别位于派生类与基类);(2)函数名字相同;(3)参数相同;(4)基类函数必须有virtual 关键字。4.3“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,特征是:

(1)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。(2)如果派生类的函数与基类的函数同名,但是参数相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

小结:说白了就是如果派生类和基类的函数名和参数都相同,属于覆盖,这是可以理解的吧,完全一样当然要覆盖了;如果只是函数名相同,参数并不相同,则属于隐藏。

4.4 三种情况怎么执行:

4.4.1 重载:看参数。

4.4.2 隐藏:用什么就调用什么。

4.4.3 覆盖:调用派生类。

2.模板3.容器
责任编辑:电影: 新少林寺