面向对象三大特性之一:继承(C++)
目录
继承的定义
基类对象和派生类对象的赋值转换
继承中的作用域
派生类与基类中成员的关系
派生类与默认成员函数的关系
继承与友元的关系
继承与静态成员的关系
面向对象的三大特性:封装,继承,多态。
继承作为三大特性之一,是使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。继承呈现了面向对象程序设计的层次结构,继承是类设计层次的复用。
继承的定义
格式的定义:
//A类为基类
class A{
public:int a;
};// B 继承于 A
class B : public A {
public:int b;
};
class B : public A 这句中 :其中B类为派生类,也叫子类;A类为基类,也叫父类;public为继承方式。
注意:继承后父类(A类)的成员(成员函数+成员变量)都会变成子类(B类)的一部分,B类也有自己的数据和方法。这里体现出了B类复用了A类的成员。B类对象可以访问到这些数据和方法,但也要有权限问题。
举个例子:
//Person类为基类
class Person{
public:string name;int age;void Print(){cout << name << " " << age << endl;}
};//Student类继承了Person
class Student : public Person{
private:int stuid: // 学号
};//Teacher类继承了Person
class Teacher : public Person{
private:int jobid;//教师职工号
};
Student类和Teacher类继承Person类,这两个类继承了Person类中的数据 ( name和age ) 和方法 ( Print() ) 。
通过复用,两个派生类都可以使用基类的数据和方法,不用再写声明相同的数据和方法,节省了代码量。
上面提到了继承的方式为public,其实还有private继承方式和protected继承方式。
下图为继承方式和访问限定符的关系图:
总结如下:
1、基类private成员在派生类中是不可见的。不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里还是类外都不能去访问它。
2、若基类成员不想在类外直接被访问,但想要在派生类中访问,就定义为protected。protected限定符是因继承才出现的。
3、class中默认为private继承,struct中默认为public继承。但最好显示的写出继承方式。
4、public继承最为常用,private/protected继承只能在类中访问,作用不大。在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承。这也是C++面向对象的较坑的一点。
基类对象和派生类对象的赋值转换
基类与派生类之间的赋值转换只能发生在公有继承中。
1、派生类赋值给基类
派生类对象可以赋值给 基类的对象/基类的指针/基类的引用。
这个行为我们可以把它叫做 切片,意思就是把派生类中基类的那部分切分开赋值给基类。如下图所示
class A
{
public:int a;int b;int c;
};class B : public A
{
public:int d = 4; //B中继承了A的a b c
};int main()
{B b;b.a = 1;b.b = 2;b.c = 3;//下面的过程叫切片//子类对象可以赋值给父类对象/指针/引用A a1 = b; A* a2 = &b; A& a3 = b; // 注意a3不是b的别名,而是其中父类部分的别名//a对象中的成员变量a b c分别等于1 2 3 return 0;
}
对象间的赋值,是将派生类从基类继承来的数据复制一份给基类对象。
指针间的赋值,是将基类的指针指向派生类的对象,但所指的范围只包括基类的数据。
引用间的赋值,引用在底层也是一个指针,所以原理指针赋值的原理基本相同。
2、基类 无法 赋值给派生类
b = a; //这是错的
3、基类的指针可以通过强制类型转换赋值给派生类的指针
基类的指针必须是指向派生类对象地址才是安全的。
//a:基类 b:派生类
A *a = &b;
B *b1 = (B*)a; //这样可以
//a:基类 b:派生类
A a1 = b //切片
A *a2 = &a1;
B *b1 = (B*)a2; //这种情况转换时虽然可以,但会存在越界访问的问题。//只能访问到基类的数据,无法访问派生类数据,是乱码。
继承中的作用域
- 继承体系中,基类和派生类都有自己独立的作用域。
- 若子类和父类中有同名的成员,子类成员将屏蔽对父类中同名的成员的直接访问,这种行为叫隐藏,也叫重定义。若想访问父类同名成员,则要使用 基类::基类成员 的格式显示访问。
- 若是成员函数的隐藏,只需让函数名相同就可以。
- 但在继承体系中,最好不要定义同名的成员。
class A
{
public:int x = 1;int y = 2;void fun(){ cout << x << " " << y << endl; //打印结果为 1 2}
};class B : public A
{
public:int x = 3; //B类中的成员x和A类中的成员X构成隐藏(重定义)int z = 4;void fun() //B类中的成员函数fun和A类中的成员函数fun构成隐藏(重定义),成员函数满足函数名相同就构成隐藏{cout << x << " " << z << endl; //打印结果为 3 4cout << A::x << endl; //打印结果为 1 ,显示的调用父类的成员}
};
派生类与基类中成员的关系
派生类与默认成员函数的关系
- 派生类的构造函数调用基类的构造函数来初始化继承字基类中的数据。如果基类中没有默认的构造函数,就在派生类构造的初始化列表阶段进行显示的调用。
- 派生类对象初始化先调用基类构造再调派生类构造。
- 派生类对象析构清理先调用派生类析构再调基类的析构。派生类的析构与基类的析构构成了隐藏(由于继承中多态的原因),析构函数不显示调用,由编译器自己调用。
- 派生类的拷贝构造调用基类的拷贝构造完成对基类数据的拷贝。
- 派生类的operator=调用基类的operator=完成对基类数据的赋值。
class A
{
protected:int x;public:A(int _x = 1):x(_x){cout << "A()" << endl;}A(const A& a):x(a.x){cout << "A(const A&)" << endl;}A& operator=(const A& a){cout << "operator=()" << endl;if (this != &a){x = a.x;}return *this;}~A(){cout << "~A()" << endl;}
};class B : public A
{
protected:int y; public:B(int _x = 1, int _y = 2):A(_x) //先调基类构造, y(_y){cout << "B()" << endl;}B(const B& b):A(b) //先调拷贝基类构造,y(b.y){cout << "B(const B&)" << endl;}B& operator=(const B& b){cout << "operator=()" << endl;if (this != &b){A::operator=(b);y = b.y;}return *this;}~B() // 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员{cout << "~B()" << endl;}
};
继承与友元的关系
友元关系不能继承(基类友元不能访问子类私有和保护成员)
继承与静态成员的关系
- 基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一 个static成员实例。
- 所有子类对静态成员的操作都只是在同一个静态成员之上。
面向对象三大特性之一:继承(C++)相关推荐
- 大数据必学Java基础(四十):面向对象三大特性之一继承(Inheritance)
文章目录 面向对象三大特性之一继承(Inheritance) 一.列举案例说明 1.类是对对象的抽象
- java 面向对象三大特性之继承 万字详解(超详细)
目录 前言 : 一.为什么需要继承: 二.什么是继承(Warning : 篇幅较长)? 1.继承概述: 2.子类继承父类之后达到的效果 : ①如何使用继承? ②代码演示 : 3.继承的使用场景: eg ...
- C++——面向对象三大特性之继承
文章目录 继承概念 继承的定义 继承的语法格式 继承方式 继承方式的汇总 赋值兼容规则 基类对象和派生类对象的赋值转换 继承中的作用域 派生类的默认成员函数 继承与友元 继承与静态成员 菱形继承 虚继 ...
- 面向对象三大特性(继承)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.今日回顾 1.<高等数学>:一节网课 2.阅读:<费马大定理>300页 3.英语:120个 ...
- 深入理解Java面向对象三大特性 封装 继承 多态
1.封装 封装的定义: 首先是抽象,把事物抽象成一个类,其次才是封装,将事物拥有的属性和动作隐藏起来,只保留特定的方法与外界联系 为什么需要封装: 封装符合面向对象设计原则的第一条:单一性原则,一个类 ...
- Java面向对象三大特性(封装继承多态)解释及案例
文章目录 包 包基本语法 命名规则 命名规范 导入包实例 访问修饰符 面向对象编程-封装 面向对象编程-继承 super关键词 super和this的比较 方法重写/覆盖 (override) 注意事 ...
- python基础学习十四:面向对象三大特性之继承
一.继承的基本概念 Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下: # ⽗类A class A(object):def __init__(self ...
- Day21 面向对象三大特性之继承
1.初识继承 什么是继承 继承是面向对象中的一个概念,是描述两个对象的关系,在程序中,继承描述的是类和类之间的关系 例如:a继承了b,a就可以使用b的属性和方法.a称之为子类,b称之为父类,也叫基类 ...
- python面向对象三大特性之继承
继承是创建新类的方法,以下是几个概念 父类,基类,超类: 被继承的类 子类,派生类:继承而产出的类 单继承:继承一个父类 多继承:继承多个父类 继承: 什么是什么的关系 父类中没有的属性,在字类中出现 ...
- python继承的特点_python面向对象三大特性之继承
继承是创建新类的方法,以下是几个概念 父类,基类,超类: 被继承的类 子类,派生类:继承而产出的类 单继承:继承一个父类 多继承:继承多个父类 继承: 什么是什么的关系 父类中没有的属性,在字类中出现 ...
最新文章
- 【Qt】Qt Creator中文输入设置
- 如何做到微信机器人不封号_电销系统是如何做到不封号的?封号对企业有什么影响?...
- 大盘点|基于RGB图像下的机器人抓取
- 爱逛街的爱购物的看看哦
- 使用ramdisk 优化nagios IO性能
- 手机投屏到电视的5种方法_安卓手机、苹果手机投屏到电视史上最全的方法
- mysql 5.6的gtid_mode_[MySQL 5.6] GTID实现、运维变化及存在的bug
- python中如何保存文件_如何在python中处理后保存文件?
- Android一个简单易用的进度条
- (15)css常用样式—background背景属性
- 实践案例丨Pt-osc工具连接rds for mysql 数据库失败
- 【操作系统】第3章 进程管理与调度
- codeforce Gym 100418K 	Cards (概率,数学)
- SQL Server 字符串拆分
- android打开iso,安卓手机端如何运行iso镜像文件
- 一直被世人误解的薛定谔猫:批判量子力学及其残忍的隐喻
- 计算机二级Python错题
- Linux useradd -M -s
- windows变量环境
- Java 的字节与字符输入/输出流的类整理——zyx笔记
热门文章
- i12单双耳切换_多种形态,切换惬意,雷柏i100蓝牙TWS耳机,支持单耳/双耳使用...
- QT vs下x64编译变win32编译报错:C:\Users\ycy\AppData\Local\QtMsBuild\qtrcc.targets(69,5): error MSB3073:
- java面向对象编程考试题,202514HJava面向对象编程答案试题题目及答案,期末考试题库,章节测验答案...
- 前端传中文文件名_前端工程师需要掌握哪些知识,web前端开发规范总结
- mysql+如何开发存储引擎_干货!MySQL 的 InnoDB 存储引擎是怎么设计的?
- 华为手机怎么看图片属性_华为手机音量小怎么办
- 分析各种排序算法的优劣
- c语言中size of 用法,C语言中sizeof()的用法
- 计算机职称excel2007,职称计算机Excel2007中文电子表格考试大纲
- php单词出现频率,PHP计算文件或数组中单词出现频率