再谈C++继承

一、三种继承方式

private     基类的公有成员与保护成员成为派生类的私有成员

public       基类的成员访问权限不变

protected     基类的公有成员与保护成员将成为派生类的保护成员

二、三种继承方式的对比:

三、在没有虚函数的情况下,类指针调用函数是注意:

  • 如果以一个基类指针指向派生类对象,那么经由该指针只能调用基类所定义的函数
  • 如果你以一个派生类的指针指向一个基类对象,你必须先做明显的强制转换,但是这样做很危险
  • 如果基类和派生类都定义了相同名的成员函数,那么通过对象指针调用成员函数时候,调用的函数是由指针的原始类型而定,而不是看指针指向的对象的类型而定

四、虚函数表:

定义:

为了达到动态绑定(后期绑定)的目的,C++编译器通过某个表格,在执行期"间接"调用实际上欲绑定的函数(注意"间接"字眼).这样的表格称为虚函数表(常被称为vtable).每一个"内含虚函数的类",编译器都会为它做一个虚函数表,表中的每一个元素都指向一个虚函数的地址.此外,编译器当然会为这个类加上一项成员变量,是一个指向这个虚函数表的指针(常被称为vptr),且每个由此派生出来的对象,都会有这个一个vptr.

介绍:

当我们通过这个对象调用虚函数时,事实上是通过vptr找到虚函数,再找出真实的地址,虚函数表用这种间接的的方式,虚函数表的内容是依据类中的虚函数声明次序,意义填入函数表(以及所有其他可以继承的成员),当我们在派生类中改写虚函数时,虚函数表就受了影响:表中元素所指的函数地址将不再是基类的函数地址,而是派生类的地址

单继承

声明格式:

class 派生类名:继承方式(若不具体指出默认为private) 基类名 {     … };

特性:

继承了基类所有属性与行为,包括私有成员,但不允许派生类直接访问基类私有成员

构造函数:

格式:   派生类构造函数名(形参表):基类构造函数名(形参表){…}

要点:

● 创建派生类对象时,程序首先创建基类对象,即基类对象应在进入派生类构造函数前被创建完成  (即先调用基类构造函数,后调用派生类构造函数) ● 派生类构造函数应通过成员初始化表将基类信息传递给基类构造函数 ● 派生类构造函数应初始化派生类新增的数据成员

析构函数:

特性:    派生类对象过期时,程序将首先调用派生类析构函数,然后调用基类的

虚析构函数:

作用:  和虚函数一样类似,在用基类指针释放派生类对象时候,为了能调用正确的析构函数.

注意:  当一个类有虚函数功能,它经常作为一个基类使用,并且它的派生类经常使用new来分配,那么它最好也使用虚析构函数,因为这样才能保证在释放实例对象的时候调用正确的析构函数

注意:

  • 构造函数的调用次序为 基类 -> 派生类
  • 析构函数的调用次序为 派生类 -> 基类

多继承

声明格式:

class 派生类名:继承方式 基类名,继承方式 基类名… {….};

构造函数:

  • 形式:

派生类名::派生类名(形参表):基类名(形参表),基类名(形参表)…{…}

  • 特点:

处理同一层的基类构造函数的执行顺序取决于定义派生类对各基类的排列顺序,与定义派生类的构造函数时基类的排列顺序无关

  • 二定义性:

原因:

  • 由于多层次的交叉派生类关系,造成一个派生类对象包含了基类成员的多个副体
  • 多个基类中某个成员名相同

方法:

  • 用虚基类来解决由于多层次的交叉派生类关系(原理:采用虚基类定义方式定义派生类,在创建派生类时,类层次结构中某个虚基类的成员只保留一个,即虚基类成员的一个副本被所有派生类共享)
  • 用基类中定义成员的访问修改方法来解决多个基类中某个成员名相同

虚基类:

声明格式:   class 派生类名:virtual 继承方式 基类名,… { … };

注意:

  • virtual与继承方式之间的次序无关且将基类作为虚基类,计算机为此完成一些额外计算量慎用
  • 一个类可以在一个类族中用作虚基类,也可以用作非虚基类.
  • 在派生类的对象中,同名的虚基类只产生一个虚基类子对象,而某个非虚基类产生各自的对象.
  • 虚基类子对象是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的.
  • 最派生类是指在继承结构中建立对象时所指定的类.
  • 在派生类的构造函数的成员初始化列表中,必须列出对虚基类构造函数的调用,如果没有列出,则表示使用该虚基类的缺省构造函数.
  • 在虚基类直接或间接派生的派生类中的构造函数的成员初始化列表中,都要列出对虚基类构造函数的调用.但只有用于建立对象的最派生类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类构造函数的调用在执行中被忽略,从而保证对虚基类子对象只初始化一次.
  • 在一个成员初始化列表中,同时出现对虚基类和非虚基类构造函数的调用时,基类的构造函数先于非虚基类的构造函数执行

有虚基类和无虚基类的区别:

  • 有虚基类:

构造函数的顺序与继承顺序有关,而不是基类构造函数的调用有关

时间: 2024-08-29 15:44:48

再谈C++继承的相关文章

Java继承之再谈构造器

目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Java>中提到下面一段话: 当创建一个导出类的对象时,该对象包含了一个基类的子对象.这个子对象与你用基类直接创建的对象是一样的.二者区别在于,后者来自于外部,而基类的子对象被包装在导出类的对象内部. 我们在创建子类对象时,调用了父类的构造器,甚至父类的父类构造器.我们知道,构造器用于创建对象,那么突然产生

C++ Primer 学习笔记_73_面向对象编程 --再谈文本查询示例

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he

Java基础——再谈面向对象

去年的这个时候,心血来潮写了篇<简述面向对象技术>,先在看来不由的会想:这都是写的什么跟什么啊?(ps:虽然现在写的博客依然不咋地)但是,Java的学习中又一次不得不再一次面向对象,所以,奉上一篇<再谈面向对象>,做为新年的一盘开胃菜. 面向对象是相对于面向过程而言,是一种思想. 区别于面向过程: 面向过程是以函数为基础,完成各种操作,强调的是过程,而面向对象是以对象为基础,强调的是对象. 比如说把大象装进冰箱分为几步,宋丹丹是这样说的:三步呗, 第一步:打开冰箱门, 第二步:把大

再谈Unity调用Android的Activity

这段时间在研究Unity4.3开发环境下,如何调用由Android SDK4.4.2写的Activity.参考了很多网上的博客,百度出了几十篇大部分都是转载雨松MOMO的,这里必须向雨松MOMO表示敬意!但雨松MOMO写的博客太旧了,不少内容已经过时,我严格按他说的步骤进行,还是出了问题,所以本博客就是告诉大家在Unity4.3+Android SDK4.4.2环境,起动Activity的细节. 我这篇博客不会从零讲起,所以首先给出两个重要的链接,大家应该看一下: 第一个是雨松MOMO的  ht

C++ Primer 学习笔记_73_面向对象编程 -再谈文本查询示范

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he

再谈MFC学习——模态对话框的数据传递

学习c++的目的就是为了使用封装好的类,而最最经典的封装类当然是微软的MFC窗口程序类.学习MFC编程之前要学习c++的主要知识,掌握c++的基本编程思想.下面就看下我学习的MFC模态对话框的数据传递. 首先,什么叫做模态对话框呢?模态对话框指的是当弹出这样的对话框的时候,程序不能相应除了此对话框外其他的窗口的响应,直到关闭了这个对话框,程序才能响应其他的对话框的响应.非模态对话框即使弹出也能响应程序其他的窗口而不需要等到此窗口的关闭.那么MFC中怎么才能弹出模态对话框呢?其实很简单,首先创建这

再谈 Object Factories(对象工厂)

为何而写: 为什么再谈一次,因为上次代码实在是不够好.上篇文章对象工厂给出的代码太过拙劣,限于学识,我自己类型擦除技术仅仅是把对象的指针转换为void* 而已,实际上可以更为巧妙.这次利用新的类型擦出技术,给出一个完美的解决方,请看下文. 前情描述: 我为什么不直接保存用户提供的function的void*而非要把他copy一份利用容器vector储存起来,然后再去取其指针转换为void*.是因为用户传来的function可能是右值或临时值,一个马上要被删除的值,如果我们直接使用用户提供的fun

Java编程思想(十八) —— 再谈反射

在Java编程思想(十五) -- 类型信息之反射和Java编程思想(十六) -- 联系JVM再谈Class,书上只用了3页就讲完了,还有讲了那么多Class的东西,接下来要从反射中怎么用,自己结合API和其他资料再写多一些. 示例:Test.java public class Test { public Test() {     }      public Test(int i) {         System.out.println(i);     } private void pri()

再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结

Angular 的数据绑定采用什么机制,详述原理? 脏检查机制.阐释脏检查机制,必须先了解如下问题. 单向绑定(ng-bind) 和 双向绑定(ng-model) 的区别? ng-bind 单向数据绑定($scope -> view),用于数据显示,简写形式是 {{}}. 两者的区别在于页面没有加载完毕 {{val}} 会直接显示到页面,直到 Angular 渲染该绑定数据(这种行为有可能将 {{val}} 让用户看到):而 ng-bind 则是在 Angular 渲染完毕后将数据显示. ng-