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 异常也就是我们经常遇到 ...
随机推荐
- spring cloud: Hystrix(六):feign的注解@FeignClient:fallbackFactory(类似于断容器)与fallback方法
fallbackFactory(类似于断容器)与fallback方法 feign的注解@FeignClient:fallbackFactory与fallback方法不能同时使用,这个两个方法其实都类似 ...
- pandas选择单元格,选择行列
首先创建示例df: df = pd.DataFrame(np.arange(16).reshape(4, 4), columns=list('ABCD'), index=list('5678')) d ...
- c++-pimer-plus-6th-chapter03
Chapter Review Having more than one integer type lets you choose the type that is best suited to a p ...
- hdu-2709整数划分 技巧
整数划分变形,由2^k组成. 整数划分中一个节约内存的技巧,平时我们使用dp[i][j]维护用不大于j的数组合成i的方案数,所以必须dp[i-j][j]->dp[i][j].这样就需要二位,如果 ...
- RMQ 解决区间查询问题
线段树写法不管,比较灵活.这里主要讨论DP实现. 其实单纯说RMQ解决的是区间最值查询是不准确的,只要满足一个区间的信息可以从它的覆盖区间获得(即[L,R]<=[L,r],[l,R] (l< ...
- android--------自定义控件 之 基本实现篇
前面简单的讲述了Android中自定义控件中的几个方法,今天通过代码来实现一个简单的案例 自定义一个扇形图 自定义控件示例: 这里先介绍继承View的方式为例 public class Circula ...
- PHP流程控制笔记
一.运算符(Operator) 1.运算符 2.运算符分类 (1)按功能分 (2)按操作数个数分 3.按功能分 (1)算术运算符 (2)递增递减 (3)字符运算符 (4)赋值运 ...
- 2018 Benelux Algorithm Programming Contest (BAPC 18)I In Case of an Invasion, Please. . .
题意:一副无向有权图,每个点有一些人,某些点是避难所(有容量),所有人要去避难所,问最小时间所有人都到达避难所, 题解:dij+二分+最大流check,注意到避难所最多10个,先挨个dij求到避难所的 ...
- nginx-exporter安装使用
一.没有vts的启动方式 #nginx_exporter -telemetry.address=:9113 -nginx.scrape_uri="http://127.0.0.1:100 ...
- python-flask-请求源码流程
启动先执行manage.py 中的 app.run() class Flask(_PackageBoundObject): def run(self, host=None, port=None, ...