C++基础知识:继承
1.继承的概念
面向对象中的继承指类之间的父子关系
子类拥有父类的所有成员变量和成员函数
子类就是一种特殊的父类
子类对象可以当作父类对象使用
子类可以拥有父类没有的方法和属性
2.C++中的访问级别与继承
public继承
父类成员在子类中保持原有访问级别
private继承
父类成员在子类中变为private成员
注意:
C++中class的继承默认为private继承
private继承的子类拥有父类的所有成员
private继承使得父类的所有成员在子类中变为private成员
3.类的protected成员
protected成员可以在子类中被访问,但不能在外界被访问
protected成员的访问权限介于public和private之间
4.类成员访问级别设置的原则
需要被外界访问的成员直接设置为public
只能在当前类中访问的成员设置为private
只能在当前类和子类中访问的成员设置为protected
private成员在子类中依然存在,但是却无法访问到!
5.继承中的构造与析构
①赋值兼容性原则
子类对象可以当作父类对象使用
子类对象可以直接赋值给父类对象
子类对象可以直接初始化父类对象
父类指针可以直接指向子类对象
父类引用可以直接引用子类对象
子类是就是特殊的父类:
②类在C++编译器的内部可以理解为结构体,子类是由父类成员叠加子类新成员得到的:
③在子类对象构造的时候需要调用父类构造函数对其继承得来的成员进行初始化:
④在子类对象析构的时候需要调用父类析构函数对其继承得来的成员进行清理
子类对象在创建时会首先调用父类的构造函数
父类构造函数执行结束后,执行子类的构造函数
当父类的构造函数有参数时,需要在子类的初始化列表中显示调用
析构函数调用的先后顺序与构造函数相反
⑤继承与组合的混搭:
如果一个类继承自父类并且有其它的对象作为成员,那么构造函数如何调用?
口诀:先父母,后客人,再自己。
⑥当子类成员变量与父类成员变量同名时:
子类依然从父类继承同名成员
在子类中通过作用域分别符::进行同名成员区分
同名成员存储在内存中的不同位置
6.继承与多态
①函数重写:
在子类中定义与父类中原型相同的函数
函数重写只发生在父类与子类之间
父类中被重写的函数依然会继承给子类
默认情况下子类中重写的函数将隐藏父类中的函数
通过作用域分辨符::可以访问到父类中被隐藏的函数
②当函数重写遇上赋值兼容性原则
问题所在:
C++与C相同,是静态编译型语言
在编译时,编译器自动根据指针的类型判断指向的是一个什么样的对象
所以编译器认为父类指针指向的是父类对象(根据赋值兼容性原则,这个假设合理)
由于程序没有运行,所以不可能知道父类指针指向的具体是父类对象还是子类对象
从程序安全的角度,编译器假设父类指针只指向父类对象,因此编译的结果为调用父类的成员函数
在编译这个函数的时候,编译器不可能知道指针 p 究竟指向了什么。
但是编译器没有理由报错。于是,编译器认为最安全的做法是编译到父类的print函数,因为父类和子类肯定都有相同的print函数。
③多态应用:C++支持两种多态性:编译时多态性,运行时多态性。
a.编译时多态性: 通过函数重载和运算符重载来实现的。
b 运行时多态性:通过继承和虚函数来实现的。
根据实际的对象类型来判断重写函数的调用
如果父类指针指向的是父类对象则调用父类中定义的函数
如果父类指针指向的是子类对象则调用子类中定义的重写函数
C++中的多态支持:
C++中通过virtual关键字对多态进行支持(传说中的虚函数)
使用virtual声明的函数被重写后即可展现多态特性
C++中多态的实现原理
当类中声明虚函数时,编译器会在类中生成一个虚函数表
虚函数表是一个存储类成员函数指针的数据结构
虚函数表是由编译器自动生成与维护的
virtual成员函数会被编译器放入虚函数表中
存在虚函数时,每个对象中都有一个指向虚函数表的指针
虚函数的深入理解:
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。
而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
对象中的VPTR指针什么时候被初始化?
对象在创建的时候由编译器对VPTR指针进行初始化
只有当对象的构造完全结束后VPTR的指向才最终确定
父类对象的VPTR指向父类虚函数表
子类对象的VPTR指向子类虚函数表
结论:构造函数中调用虚函数无法实现多态。
虚函数:在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态重载
纯虚函数:纯虚函数是只声明函数原型,而故意不定义函数体的虚函数。
面向对象中的抽象类:抽象类可用于表示现实世界中的抽象概念,包含纯虚函数的类称为抽象类
抽象类是一种只能定义类型,而不能产生对象的类
抽象类只能被继承并重写相关函数
抽象类的直接特征是纯虚函数
抽象类不能用于定义对象
抽象类只能用于定义指针和引用
抽象中的纯虚函数必须被子类重写
④函数的重载/重写
C++基础知识:继承的更多相关文章
- JAVA基础知识|继承的几个问题
1.子类从父类继承了什么? 子类拥有父类非private的属性,方法. 2.子类可以操作父类的非private属性吗? 子类不能继承父类的私有属性,但是如果父类中的非private方法影响到了私有属性 ...
- java基础知识—继承
1.不能被继承的父类成员: private成员.子类与父类不在同包,使用默认访问权限的成员.构造方法. 2.访问修饰符: 访问修饰符 本类 同包 子类 其它 ...
- 20151024_004_C#基础知识(C#中的访问修饰符,继承,new关键字,里氏转换,is 和 as,多态,序列化与反序列化)
1:C#中的访问修饰符 public: 公共成员,完全公开,没有访问限制. private: 私有的,只能在当前类的内部访问. protected: 受保护的,只能在当前类的内部以及该类的子类中访问. ...
- Servlet学习笔记【1】--- 背景和基础知识(CGI、Web服务器发展史、Servlet简介、任务、继承结构)
本文主要讲Servlet的基础知识和背景知识. 1 CGI简介 CGI(Common Gateway Interface 公共网关接口)是WWW技术中最重要的技术之一,有着不可替代的重要地位.CGI是 ...
- c++ 基础知识回顾 继承 继承的本质就是数据的copy
c++ 基础知识笔记 继承 什么是继承 继承就是子类继承父类的成员属性以及方法 继承的本质就是 数据的复制 是编译器帮我们做了很多操作 class Base { public: Base(){ cou ...
- 《Java核心技术·卷Ⅰ:基础知识(原版10》学习笔记 第5章 继承
<Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 目录 <Java核心技术·卷Ⅰ:基础知识(原版10>学习笔记 第5章 继承 5.1 类.超类和子类 5.1 ...
- 【干货】用大白话聊聊JavaSE — ArrayList 深入剖析和Java基础知识详解(二)
在上一节中,我们简单阐述了Java的一些基础知识,比如多态,接口的实现等. 然后,演示了ArrayList的几个基本方法. ArrayList是一个集合框架,它的底层其实就是一个数组,这一点,官方文档 ...
- java基础知识 多线程
package org.base.practise9; import org.junit.Test; import java.awt.event.WindowAdapter; import java. ...
- Linux基础知识整理
一.基础知识 1.Linux简介 Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.它能运行主要的UNIX工具软件 ...
- 基础知识《十》unchecked异常和checked异常
运行时异常在运行期间才能被检查出来,一般运行期异常不需要处理.也称为unchecked异常.Checked异常在编译时就能确定,Checked异常需要自己处理. checked 异常也就是我们经常遇到 ...
随机推荐
- 【转】 C语言文件操作详解
转自:http://www.cnblogs.com/likebeta/archive/2012/06/16/2551780.html C语言中没有输入输出语句,所有的输入输出功能都用 ANSI C提供 ...
- java ----> 类转换异常
com.rr.domain.Department_$$_javassist_5 cannot be cast to javassist.util.proxy.Proxy 两个原因: 1.懒加载 在we ...
- Lab 3-4
Analyze the malware found in the file Lab03-04.exe using basic dynamic analysis tools. (This program ...
- mybatis中的mapper接口文件以及selectByExample类的实例函数详解
记录分为两个部分,第一部分主要关注selectByExample类的实例函数的实现:第二部分讨论Mybatis框架下基本的实例函数. (一)selectByExample类的实例函数的实现 当你启动项 ...
- 『TensorFlow』第七弹_保存&载入会话_霸王回马
首更: 由于TensorFlow的奇怪形式,所以载入保存的是sess,把会话中当前激活的变量保存下来,所以必须保证(其他网络也要求这个)保存网络和载入网络的结构一致,且变量名称必须一致,这是caffe ...
- SpringBoot项目Shiro的实现(二)
在看此小节前,您可能需要先看:http://www.cnblogs.com/conswin/p/7478557.html 紧接上一篇,在上一篇我们简单实现了一个Springboot的小程序,但我们发现 ...
- call、apply、bind三者的区别
先构造函数let xiaowang={ name1:"小王", age:", sex:"男", say:function(){ console.log ...
- PHP手册-函数参考-日期与时间相关扩展
一.Calander.日期/时间.HRTime扩展的对比 Calendar 日期/时间 HRTime 简介 历法扩展集包括了一系列用于在不同历法间进行转换的函数,它是以Julian Day计数为中 ...
- git如何merge github forked repository里的代码更新?(转)
参考内容:git如何merge github forked repository里的代码更新? [refer to ]http://www.haojii.com/2011/08/how-to-git- ...
- HBase环境搭建、shell操作及Java API编程
一. 1.掌握Hbase在Hadoop集群体系结构中发挥的作用和使过程. 2.掌握安装和配置HBase基本方法. 3.掌握HBase shell的常用命令. 4.使用HBase shell命令进行表的 ...