C++面向对象程序设计学习笔记(5)
派生类与继承
概念
继承允许编程者在已有类的基础上创建新的类,可以从一个或者多个已有类中继承函数和数据,并重新定义或者添加新的函数和数据,已有类称为基类或父类,新类称为派生类和子类。
声明
声明一个派生类的一般格式为:
class 派生类名 : [继承方式] 基类名
{
派生类新增的数据成员和成员函数
};
继承方式种类有 private, public ,protected ,分别为私有、公有和保护继承
若不显式地给出关键字,则默认为私有
构成
构造一个派生类包括三部分公作:
1)派生类从基类接受成员
派生类将基类除构造函数和析构函数以外的全部成员全部接收
2)调整从基类接收来的成员
调整包括两个方面 改变基类成员在派生类中的访问属性(通过继承方式实现)
对基类成员重定义(派生类的同名成员会覆盖基类中的同名成员)
3)在派生类中添加新的成员
基类成员在派生类中的访问属性
| 基类中的成员 | 在公有派生类中的访问属性 | 在私有派生类中的访问属性 | 在保护派生类中的访问属性 |
|---|---|---|---|
| 私有成员 | 不可直接访问 | 不可直接访问 | 不可直接访问 |
| 公有成员 | 公有 | 私有 | 保护 |
| 保护成员 | 保护 | 私有 | 保护 |
派生类对基类成员的访问规则
派生类对基类成员的访问形式主要有两种:
(1)内部访问 由派生类中新增的成员函数对基类继承来的成员的访问
(2)对象访问 在派生类外部,通过派生类对象对从基类继承来的成员的访问
私有继承的访问规则
| 基类中的成员 | 私有成员 | 公有成员 | 保护成员 | |
|---|---|---|---|---|
| 访问方式 | 内部访问 | 不可访问 | 可访问 | 可访问 |
| 对象访问 | 不可访问 | 不可访问 | 不可访问 | |
公有继承的访问规则
| 基类中的成员 | 私有成员 | 公有成员 | 保护成员 | |
|---|---|---|---|---|
| 访问方式 | 内部访问 | 不可访问 | 可访问 | 可访问 |
| 对象访问 | 不可访问 | 可访问 | 不可访问 | |
保护继承的访问规则
| 基类中的成员 | 私有成员 | 公有成员 | 保护成员 | |
|---|---|---|---|---|
| 访问方式 | 内部访问 | 不可访问 | 可访问 | 可访问 |
| 对象访问 | 不可访问 | 不可访问 | 不可访问 | |
派生类的构造函数和析构函数
基类的构造函数和析构函数不能被继承,所有从派生类的初始化需要加入派生类的构造函数,而基类继承下来的成员的初始化还是有基类的构造函数完成的,析构函数同理。
执行顺序
创建派生类对象时,先执行基类构造函数,再执行派生类的构造函数,
在撤销派生类对象时,先执行派生类析构函数,再执行基类的析构函数。
构造规则
简单派生类的构造函数
派生类构造函数的一般格式为
派生类名(参数总表):基类名(参数表)
{
派生类新增数据成员的初始化语句
}
基类构造函数的参数通常来自于派生类构造函数的参数总表,也可以用常数值
若基类使用默认构造函数或不带参数的构造函数,则可略去基类的构造函数,若此时不需要构造函数,则可不定义派生类构造参数
当基类构造函数中存在参数,则派生类必须定义构造函数
含有对象成员的派生类的构造函数
构造参数的一般形式为
派生类名(参数总表):基类名(参数表0),对象成员名1(参数表 1),......,对象成员名n(参数表 n)
{
派生类新增数据成员的初始化语句
}
该构造函数执行顺序如下:
+调用基类的构造函数;
+调用内嵌对象成员的构造函数;
+执行派生类的构造函数体;
注意:
1.当派生类中含有多个内嵌对象成员时,调用内嵌对象成员的构造函数顺序由它们在类中的声明顺序决定
2.若派生类的基类也是派生类,则每个派生类只需负责其直接基类数据成员的初始化
调整基类成员在派生类中的访问属性的其他方法
同名成员
派生类可以重新说明与基类成员同名的成员,在派生类使用该名字意味着访问在派生类中重新定义的成员,若要访问基类的同名成员,则需要在该成员名前加上基类名和作用域标识符"::"
例:
class X
{
public:
X();
~X();
void f();
};
class Y:public X
{
public:
Y();
~Y();
void f();
};
//若要访问派生类中的f(),则调用函数f()或Y::f()
//若要访问基类中的f(),则调用函数X::f()
访问声明
对于私有继承,外界无法利用派生类的对象直接调用基类的成员函数,只能通过调用派生类的成员函数间接调用基类的成员函数
C++提供类称为访问声明的特殊机制,可以个别调整基类中的某些成员,使之在派生类中保持原有的访问属性
访问声明的方法就是把基类的保护或公有成员直接写至私有派生类定义式中的同名段中,同时冠以基类名和作用域标识符"::",利用这种方法该成员即成为派生类的保护和公有成员
例
class X:private Y
{
public:
X();
~X();
A::print;
};
注意:
1.数据成语也可以使用访问声明
2.访问声明中只含不带类型和参数的函数名和变量名
3.访问声明不能改变成员在基类中的访问属性
4.对于基类中的重载函数名,访问声明将对基类中的所有同名函数起作用
多重继承
当一个派生类具有两个或多个基类时,即称为多重继承或多基继承。
多重继承派生类的声明
声明一般形式如下
class 派生类名 : 继承方式1 基类1 ,......,继承方式n 基类n
{
派生类新增的数据成员和成员函数
}
继承方式即:private,pubilc,protected,默认继承方式为 private
注意:对基类成员的访问必须是无二义的
多重继承派生类的构造函数和析构函数
多重继承派生类的构造函数的一般形式如下:
派生类名(参数总表):基类名1(参数表1),基类名2(参数表2),......,基类名n(参数表n)
{
派生类新增成员的初始化语句
}
多重继承派生类的构造函数与单继承下派生类构造函数相似,它必须同时负责该派生类所有基类构造函数的调用。同时,派生类的参数个数必须包含完成所有基类初始化所需的参数个数
多重继承派生类的构造函数与单继承下派生类构造函数的执行顺序相同,也是遵循先执行基类的构造函数,再执行对象成员的构造函数,最后执行派生类的构造函数体的原则。
析构函数与单继承的情况类似
虚基类
虚基类的意义:避免产生二义性
虚基类的概念
在c++中,如果想使这个公共的基类只产生一个复制,则可以将这个基类说明为虚基类。
虚基类在派生类中声明,其语法形式如下:
class 派生类名:virtual 继承方式 基类名
{
......
}
虚基类的初始化
虚基类的初始化与一般的多继承的初始化在语法上是一样的,但构造函数的调用顺序不同。
注意:
1.如果在虚基类中定义带有形参的构造函数,并且没有定义默认形式的构造参数,则整个继承结构中,所有直接或间接的派生类都必须在构造函数的成员初始化列表中列出对虚基类构造函数的调用。
2.建立一个对象时,如果这个对象中含有从虚基类继承来的成员,则虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
3.若同一个层次中同时包含虚基类和非虚基类,应先调用虚基类的构造函数,再调用非虚基类的构造函数,最后调用派生类构造函数。
4.虚基类不影响构造函数的调用顺序。
说明:
1.关键字virtual和派生方式关键字(public 或 private)的先后顺序无关紧要。
2.一个基类既可以作为某些派生类虚基类,也可以作为另一些派生类的非虚基类。
基类与派生类对象之间的赋值兼容关系
在一定条件下,不同类型的数据之间可以进行类型转换,这种不同类型数据之间的自动转换和赋值称为赋值兼容
在基类与派生类对象之间的赋值兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类的对象来替代
在基类对象可以使用的任何地方,都可以使用派生类的对象来替代,但只能使用从基类继承来的成员,具体表现在以下几个方面。
1.派生类对象可以向基类对象赋值
2.派生类对象可以初始化基类对象的引用
3.派生类对象的地址可以赋给指向基类对象的指针
4.如果函数的形参是基类对象或基类对象的引用,在调用函数时可以用派生类对象作为实参
说明:
1.声明为指向基类对象的指针可以指向它的公有派生的对象,但不允许指向它的私有派生的对象
2.允许将一个声明为指向基类的指针指向其公有派生类的对象,但是不能将一个声明为指向派生类对象的指针指向其基类的一个对象
C++面向对象程序设计学习笔记(5)的更多相关文章
- C++面向对象程序设计学习笔记(1)
基本概念 对象: 面向对象程序设计中,对象是描述其属性的数据以及对这些数据施加的一组操作封装在一起构成的统一体,每个对象都是由数据和操作代码两部分构成的. 类: 面向对象程序设计中,类是具有相同的数据 ...
- C++面向对象程序设计学习笔记(6)
多态性 编译时的多态性与运行时的多态性 在面向对象方法中,所谓多态性就是不同对象收到相同信息时,产生不同的行为.在c++程序设计中,即"一个接口,多种方法" 在C++中,多态性的实 ...
- C++面向对象程序设计学习笔记(7)
模板与异常处理 模板的概念 模板是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型作为参数. 模板分为函数模板和类模板,它们分别允许用户构造模板类和模板函数 函数模板与模板函数 函数模板实际 ...
- C++面向对象程序设计学习笔记(4)
类与对象(2) string类 C++不仅向下兼容C的字符表示方法,也声明了一种更方便的字符串类型,即string类. 想要使用string类,必须包括头文件string,即要声明 #include& ...
- C++面向对象程序设计学习笔记(3)
类与对象(1) 结构体与类 结构体的扩充 C++对结构体进行了扩充,它不仅可以含有不同类型的数据,还可以含有函数,结构体的函数可以像访问结构体中的数据一样进行访问. 类的声明 声明类的方法与声明结构体 ...
- C++面向对象程序设计学习笔记(2)
C++在非面向对象方面的扩充 C++向下兼容C语言,因此C语言中的语法在C++中依然成立 输入输出 C++添加了标准输入流对象cin和标准输出流对象cout来进行输入输出, 例: #include&l ...
- 20145213《Java程序设计学习笔记》第六周学习总结
20145213<Java程序设计学习笔记>第六周学习总结 说在前面的话 上篇博客中娄老师指出我因为数据结构基础薄弱,才导致对第九章内容浅尝遏止地认知.在这里我还要自我批评一下,其实我事后 ...
- Java程序设计学习笔记(一)
时间:2015-6-2 23:04 程序员,程序猿,程序媛,码农 ------------------------------------------------------- --Java的应用 ...
- JavaScript高级程序设计---学习笔记(二)
面向对象程序设计1.属性类型.定义多属性.读取属性特性对象的属性在创建时都带有一些特征值,JavaScript通过这些特征值来定义它们的行为.这些特性是为了实现JavaScript引擎用的,因此不能直 ...
随机推荐
- POJ3104Drying(二分)
传送门 题目大意:n件衣服,每件有ai水分.每分钟可自然风干1个水分,或者放入机器中风干k个水分. 问最少花多长时间,衣服全干. 代码: #include<iostream> #inclu ...
- FFT/NTT基础题总结
在学各种数各种反演之前把以前做的$FFT$/$NTT$的题整理一遍 还请数论$dalao$口下留情 T1快速傅立叶之二 题目中要求求出 $c_k=\sum\limits_{i=k}^{n-1}a_i* ...
- Java连载1-概述&常用的dos命令
本想写完那两个再开始新的,然而客观条件不允许,之前从未接触过Java,从零开始吧!!! 一.概述 C盘下:programme file 一般为64位程序安装的目录,programme file(X ...
- oracle like模糊查询不能走索引?
这里要纠正一个网上很多教程说的模糊匹配不能走索引的说法,因为在看<收获,不止SQL优化>一书,里面举例说到了,并且自己也跟着例子实践了一下,确实like一些特殊情况也是可以走索引的 例子来 ...
- RoadMap:如何创建产品路线图
(1)什么是Roadmap? RoadMap/产品路线图 Roadmap通常翻译为“路线图”或“蓝图”,目前并没有一个公认的定义.在这里,我们认为Roadmap是产品经理进行产品管理的一个中长期规划, ...
- Windows重要的win键
win+↓ 当前窗口操作,多按几下就缩没了(同理,其他箭头也一样) win+e 打开此电脑 win+v 展开剪切板 win+k 访问蓝牙 win+a win10的通知 win+d (切到桌面,再用能切 ...
- centos6利用cgroup冻结一个程序运行
操作步骤: 安装cgroup服务 yum install libcgroup 配置cgroup vim /etc/cgconfig.conf group stopit{ #添加一个cgroup组 fr ...
- DAX 第九篇:文本函数
DAX中用于处理文本的函数,和其他语言很相似. 一,文本连接 文本连接也可以使用操作符 & 来实现,也可以使用函数CONCATENATE来实现: CONCATENATE(<text1&g ...
- Elastic Stack核心产品介绍-Elasticsearch、Logstash和Kibana
Elastic Stack 是一系列开源产品的合集,包括 Elasticsearch.Kibana.Logstash 以及 Beats 等等,能够安全可靠地获取任何来源.任何格式的数据,并且能够实时地 ...
- Elasticsearch(ES) 下载&安装
欢迎关注笔者的公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site/ ...