关于C++中的虚拟继承的一些总结

时间:2022-08-30 13:30:02
1.为什么要引入虚拟继承

虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下:

class A

class B1:public virtual A;

class B2:public virtual A;

class D:public B1,public B2;

虚拟继承在一般的应用中很少用到,所以也往往被忽视,这也主要是因为在C++中,多重继承是不推荐的,也并不常用,而一旦离开了多重继承,虚拟继承就完全失去了存在的必要因为这样只会降低效率和占用更多的空间。

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:public virtual a   class b :public a           };                };
{              {                class b:public virtual a      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 覆盖:调用派生类。

            学习中的一点总结,欢迎拍砖哦^^

关于C++中的虚拟继承的一些总结的更多相关文章

  1. 从汇编看c++中的虚拟继承及内存布局(二)

    下面是c++源码: class Top {//虚基类 public: int i; Top(int ii) { i = ii; } virtual int getTop() { cout <&l ...

  2. C&plus;&plus;中的虚继承 &amp&semi; 重载隐藏覆盖的讨论

    虚继承这个东西用的真不多.估计也就是面试的时候会用到吧.. 可以看这篇文章:<关于C++中的虚拟继承的一些总结> 虚拟基类是为解决多重继承而出现的. 如:类D继承自类B1.B2,而类B1. ...

  3. c&plus;&plus;面试常用知识&lpar;sizeof计算类的大小,虚拟继承,重载,隐藏,覆盖&rpar;

    一. sizeof计算结构体 注:本机机器字长为64位 1.最普通的类和普通的继承 #include<iostream> using namespace std; class Parent ...

  4. C&plus;&plus; 虚拟继承

    1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念.虚拟基类是为解决多重继承而出现的.如:类D继承自类B1.B2,而类B1.B2都继 承自类A,因此在类D中两次出现类A中的变量和函数.为了节省内 ...

  5. 继承虚函数浅谈 c&plus;&plus; 类,继承类,有虚函数的类,虚拟继承的类的内存布局,使用vs2010打印布局结果。

    本文笔者在青岛逛街的时候突然想到的...最近就有想写几篇关于继承虚函数的笔记,所以回家到之后就奋笔疾书的写出来发布了 应用sizeof函数求类巨细这个问题在很多面试,口试题中很轻易考,而涉及到类的时候 ...

  6. 关于虚拟继承类的大小问题探索,VC&plus;&plus; 和 G&plus;&plus; 结果是有区别的

    昨天笔试遇到个 关于类占用的空间大小的问题,以前没怎么重视,回来做个试验,还真发现了问题,以后各位笔试考官门,出题时请注明是用什么编译器. vc6/vc8 cl 和 Dev-C 的g++ 来做的测试: ...

  7. c&plus;&plus;,为什么要引入虚拟继承

      虚拟基类是为解决多重继承而出现的.   以下面的一个例子为例: #include <iostream.h> #include <memory.h> class CA { i ...

  8. C&plus;&plus;中的类继承(4)继承种类之单继承&amp&semi;多继承&amp&semi;菱形继承

    单继承是一般的单一继承,一个子类只 有一个直接父类时称这个继承关系为单继承.这种关系比较简单是一对一的关系: 多继承是指 一个子类有两个或以上直接父类时称这个继承关系为多继承.这种继承方式使一个子类可 ...

  9. C&plus;&plus;多重继承与虚拟继承

    本文只是粗浅讨论一下C++中的多重继承和虚拟继承. 多重继承中的构造函数和析构函数调用次序 我们先来看一下简单的例子: #include <iostream> using namespac ...

随机推荐

  1. Loadrunner监控Linux系统资源

    一.安装rsh和rpcbind 1.查看是否安装:rpm -qa |grep rsh 2.安装rsh:yum -y install rsh* 3.yum  -y install nfs-utils r ...

  2. 123——Appium Girls活动

    有感于Ruby Girls和Python Girls,在15年就想组织一次移动测试的妹子活动,框架选择Appium, 从15年夏天开始准备,申请Google的会议室,招募教练,开放报名,审核报名,到正 ...

  3. 高手详解SQL性能优化十条建议

    1.查询的模糊匹配  尽量避免在一个复杂查询里面使用 LIKE '%parm1%'—— 红色标识位置的百分号会导致相关列的索引无法使用,最好不要用. 解决办法: 其实只需要对该脚本略做改进,查询速度便 ...

  4. ubuntu 重置密码

      背景:在登陆ubuntu之后,按Ctr+Alt+F1进入控制台时,需要登陆,一时忘了密码... 参考:http://www.cnblogs.com/relaxgirl/p/3179507.html ...

  5. 补充&colon;tableView优化总结

    tableView优化方式总结 (说明:一下只是我自己的小总结,会有不足,望大神指正,多谢大家了) 1 缓存 cell 的行高.目的方便第二遍访问 cell. 2 减少图片的blend 操作.包括:设 ...

  6. 判断IE版本的语句 &lbrack;if lte IE 6&rsqb;&period;&period;&period;&lbrack;endif&rsqb;

    <!–[if lte IE 6]>……<![endif]–>Ite:less than or equal to意思是小于或等于IE6浏览器,用于IE浏览器的条件注释,常用于CS ...

  7. java笔记3之赋值运算符

    赋值运算符:        基本的赋值运算符:=            把=右边的数据赋值给左边.          扩展的赋值运算符:+=,-=,*=,/=,%=            += 把左边 ...

  8. background-size做自适应的背景图

    background-size做自适应的背景图 在我们做页面布局的时候往往会遇到这样的情况当我固定一个元素的尺寸,在像元素加入背景的时候发现背景图片的原始尺寸很大,当我把背景图写入时往往超过元素很大一 ...

  9. h5新增属性

    localStorage,sessionStorage,video,audio的使用方法 <!DOCTYPE html> <html lang="en"> ...

  10. python接口自动化测试十九:函数

    # 函数 a = [1, 3, 6, 4, 85, 32, 46]print(sum(a)) # sum,求和函数 def add(): a = 1, b = 2, return a + bprint ...