C++基础——继承(上)

一、继承的概念

继承 (inheritance) 机制是面向对象程序设计使代码可以复用的最重要的手段,它允许实现者保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称之为派生类;

继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程;

以前,我们接触的复用都是函数复用,继承是类设计层次的复用。  

继承所表达的是类之间相关的关系,这种关系使得对象可以继承另外一类对象的特征和能力。

继承的作用:避免公用代码的重复开发,减少代码和数据冗余。

二、继承关系

继承基类成员访问方式的变化 

三种继承方式代码示例:

//基类
class A
{
public:
	int mA;
protected:
	int mB;
private:
	int mC;
};

//1. 公有(public)继承
class B : public A{
public:
	void PrintB(){
		cout << mA << endl; //可访问基类public属性
		cout << mB << endl; //可访问基类protected属性
		//cout << mC << endl; //不可访问基类private属性
	}
};
class SubB : public B{
	void PrintSubB(){
		cout << mA << endl; //可访问基类public属性
		cout << mB << endl; //可访问基类protected属性
		//cout << mC << endl; //不可访问基类private属性
	}
};
void test01(){

	B b;
	cout << b.mA << endl; //可访问基类public属性
	//cout << b.mB << endl; //不可访问基类protected属性
	//cout << b.mC << endl; //不可访问基类private属性
}

//2. 私有(private)继承
class C : private A{
public:
	void PrintC(){
		cout << mA << endl; //可访问基类public属性
		cout << mB << endl; //可访问基类protected属性
		//cout << mC << endl; //不可访问基类private属性
	}
};
class SubC : public C{
	void PrintSubC(){
		//cout << mA << endl; //不可访问基类public属性
		//cout << mB << endl; //不可访问基类protected属性
		//cout << mC << endl; //不可访问基类private属性
	}
};
void test02(){
	C c;
	//cout << c.mA << endl; //不可访问基类public属性
	//cout << c.mB << endl; //不可访问基类protected属性
	//cout << c.mC << endl; //不可访问基类private属性
}
//3. 保护(protected)继承
class D : protected A{
public:
	void PrintD(){
		cout << mA << endl; //可访问基类public属性
		cout << mB << endl; //可访问基类protected属性
		//cout << mC << endl; //不可访问基类private属性
	}
};
class SubD : public D{
	void PrintD(){
		cout << mA << endl; //可访问基类public属性
		cout << mB << endl; //可访问基类protected属性
		//cout << mC << endl; //不可访问基类private属性
	}
};
void test03(){
	D d;
	//cout << d.mA << endl; //不可访问基类public属性
	//cout << d.mB << endl; //不可访问基类protected属性
	//cout << d.mC << endl; //不可访问基类private属性
}

而以上三种继承方式,对于基类的私有成员(成员属性/成员方法)在派生类中不可见,即不论在派生类的类外还是类内都不可以访问:

三、继承方式总结

基类 private 成员在派生类中无论以什么方式继承都是不可见的。 这里的不可见指的是基类的私有成员虽然被继承到了派生类对象中,但是语法上限制了派生类对象访问它,无论是在派生类的类内还是类外,都无法访问;
如果基类成员不想让派生类在类外访问,但需要让派生类类内可以访问,那么该基类成员就可以定义为 protected,可以看到,protected 在继承角度有着很大的存在意义;
我们总结一下就会发现,除开基类的私有成员,基类的其他成员被子类继承后的访问方式 == Min (基类成员的访问限定符, 继承方式),private < protected < public;
class 的默认继承方式是 private,struct 的默认继承方式是public,但实际中,最好显示声明继承方式;
事实上,大多数的实际运用中,public 继承占绝大多数, 几乎很少使用 protected/private 继承,也不提倡 protected/private 继承, 因为 protected/private 继承下来的成员只能在派生类的类内使用,实际中扩展性并不强。

四、派生类的默认成员函数

默认成员函数即便我们不写,编译器也会自动生成一份,那么在派生类中,这些成员函数如何处理呢?

  • 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员,如果基类没有默认的构造函数,则必须在派生类的构造函数的初始化列表阶段显式初始化基类的成员属性;
  • 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类成员属性的初始化;
  • 派生类的 operator= 必须要调用基类的 operator= 完成基类成员属性的赋值;
  • 派生类的析构函数会在调用完成后自动调用基类的析构函数清理基类成员属性,因为这样才能保证派生类对象先清理派生类的成员属性再清理基类的成员属性;
  • 派生类对象初始化资源时 (调用构造),先初始化基类成员属性,后初始化派生类成员属性;
  • 派生类对象清理资源时 (调用析构),先清理派生类资源,在清理基类资源,即先调用派生类析构,然后编译器自动调用基类析构;
  • 我们知道,重写的条件之一是函数名相同,可是基类和派生类的析构函数的函数名不相同啊,实际上,当派生类继承基类后,编译器会对析构函数进行特殊处理,析构函数的函数名统一为 destructor,所以,如果基类的析构函数不是虚函数,那么基类析构函数和父类析构函数构成隐藏关系。

我们一共学过六个默认成员函数:

1.派生类的构造函数

        实例化一个派生类的对象后,结果却调用了基类的构造;

        如果此时基类没有默认构造,那么实例化派生类对象时,会发生编译报错。

        因此,实现者往往需要自己显式定义派生类的构造函数。

对于派生类的构造函数来说:

  • 对于派生类的成员属性,跟以前的处理方式一样( 对于内置类型不处理,对于自定义类型调用它的默认构造函数 );
  • 对于基类的成员属性,必须调用基类的构造函数初始化

2.派生类的拷贝构造

对于派生类的拷贝构造来说:

  • 对于派生类成员属性,跟以前的处理方式一样( 对于内置类型按照字节序的方式进行拷贝,对于自定义类型调用它的拷贝构造函数 );
  • 对于基类成员属性,必须调用基类的拷贝构造函数初始化基类成员属性

对于继承的基类成员而言,需要调用基类的拷贝构造初始化基类的成员属性。

3.派生类的赋值运算符重载

对于派生类来说,编译器默认生成的赋值运算符重载会:

  • 对于自己本身的成员,跟以前的处理方式一样(对于内置类型按照字节序的方式进行拷贝,对于自定义类型调用它的赋值运算符重载);
  • 对于继承父类的成员,必须调用父类的赋值运算符重载;

译器默认生成的赋值运算符重载会调用父类的赋值运算符重载; 

4.派生类的析构函数

对于派生类来说,编译器默认生成的析构函数,分两种情况:

  • 对于自身的成员,对内置类型不处理,对自定义类型去调用它的析构函数,根以前一样;
  • 对于继承的成员,需要去调用父类的析构函数处理。

而对于派生类来说,它需要保证:

派生类对象初始化时,基类成员先初始化 (先调用基类构造),派生类成员后初始化 (后调派生类构造);
派生类对象清理时,派生类成员先释放资源 (先调用派生类析构),基类成员后释放资源 (后调用基类析构);
因此编译器为了确保这种顺序,会自动调用基类的析构函数,不需要我们显式调用基类的析构函数。

5.取地址重载和const取地址重载

这两个函数跟以前一样,不需要做特殊处理,一般情况下我们也没必要显示实现;

四、继承与友元

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。


class worker;
// 基类
class person
{
public:
	friend void display(const person& pobj, const worker& wobj);
protected:
	string _name = "haha";
};
// 派生类
class worker : public person
{
protected:
	string _job_number = "111";
};

void display(const person& pobj, const worker& wobj)
{
	cout << pobj._name << endl;
	cout << wobj._job_number << endl;
}

void Test1(void)
{
	person pobj;
	worker wobj;
	display(pobj, wobj);
}

这段代码编译器会报错,提示 wobj._job_number 不可访问;

总而言之, 友元关系不可以从基类继承到派生类中,并且友元要慎用且不宜多用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/624373.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

升级Microsoft 365后,SAP GUI中无法打开Excel的解决方案

最近&#xff0c;我们遇到了一个棘手的问题&#xff0c;一位客户在升级到Microsoft 365后&#xff0c;无法在SAP GUI中打开Excel。这个问题不仅影响了工作效率&#xff0c;也给用户的日常操作带来了不便。在本文中&#xff0c;我们将探讨问题的成因&#xff0c;并提供一种解决方…

2024年【河北省安全员B证】考试及河北省安全员B证复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 河北省安全员B证考试参考答案及河北省安全员B证考试试题解析是安全生产模拟考试一点通题库老师及河北省安全员B证操作证已考过的学员汇总&#xff0c;相对有效帮助河北省安全员B证复审模拟考试学员顺利通过考试。 1、…

[vue] nvm

nvm ls // 看安装的所有node.js的版本nvm list available // 查显示可以安装的所有node.js的版本可以在可选列表里。选择任意版本安装&#xff0c;比如安装16.15.0 执行&#xff1a; nvm install 16.15.0安装好了之后。可以执行&#xff1a; …

【2024】最新快手小游戏项目,边玩游戏边赚钱,周赚4000+!快手怎么赚钱,快手干货分享!

大家好&#xff0c;我是一个99年互联网创业者。 相信老朋友对我也不陌生啦&#xff01; 但还是有一些新朋友&#xff0c;在这里我再做个简单的自我介绍吧。 我是做网赚出身的&#xff0c;大大小小的项目都接触过&#xff0c;后面转型做互联网开发程序这块&#xff0c;到现在…

更快!更自然!OpenAI推出GPT-4o,记者实测→

导读&#xff1a;第一财经记者使用GPT-4o来描述图片&#xff0c;发现其生成结果较准确&#xff0c;5秒左右就能生成描述图片的文字。 当地时间5月13日&#xff0c;OpenAI通过直播展示了产品更新。与此前传出的市场消息不同&#xff0c;OpenAI并未推出搜索引擎&#xff0c;也未…

常见加解密算法02 - RC4算法分析

RC4是一种广泛使用的流密码&#xff0c;它以其简洁和速度而闻名。区别于块密码&#xff0c;流密码特点在于按位或按字节来进行加密。 RC4由Ron Rivest在1987年设计&#xff0c;尽管它的命名看起来是第四版&#xff0c;实际上它是第一个对外发布的版本。 RC4算法的实施过程简洁…

OpenText ETX 助力 SMS 集团提高生产力、降低成本并实现全球协作

OpenText ETX 助力 SMS 集团提高生产力、降低成本并实现全球协作 SMS 集团存在的挑战 需要一个可以在全球范围内轻松访问的解决方案&#xff1b;需要一个系统&#xff0c;能够无缝运行图形要求苛刻的基于服务器的应用程序&#xff1b; 结果 1、通过全球用户访问数据&#x…

el-table组件选中后使用toggleRowSelection无法取消已选中的数据——bug记录-骚操作解决

先说本文重点解决的问题&#xff1a; 存在的问题&#xff1a;当右侧已选中的数据中&#xff0c;删除了左侧其他页面的数据&#xff0c;但是左侧数据切换到其他页面后&#xff0c;左侧还保留选中的状态。 最近在写后台管理系统的时候&#xff0c;遇到一个需求&#xff1a; 左…

鬼畜作品创作必备素材,鬼畜自学语音包合集

一、素材描述 鬼畜是什么&#xff1f;鬼畜是一种网络流行语&#xff0c;也是网络文化的一种表现形式。它指的是将原本无关的两个或多个视频、音频、图片或文字进行剪辑、混合、重组等处理后&#xff0c;形成一种新的有趣、诙谐或恶搞的作品。鬼畜的制作过程通常需要一定的技术…

使用PyQt5设计订单查询界面—了解界面布局2

想要实现的界面效果 增加Tab Widge的页签 在MainWindow窗口中选中水平布局&#xff0c;将一个Label控件和一个默认自带两个页签的Tab Widget控件放到水平布局中&#xff0c;Tab Widget控件右键选择“插入页”再选择“在当前页之后”增加页签。 为每一个Tab页签界面都选择“栅格…

【学习笔记】C++每日一记[20240513]

简述静态全局变量的概念 在全局变量前加上static关键字&#xff0c;就定义了一个静态全局变量。通常情况下&#xff0c;静态全局变量的声明和定义放在源文件中&#xff0c;并且不能使用extern关键字将静态全局变量导出&#xff0c;因此静态全局变量的**作用于仅限于定义静态全…

【driver6】debugfs,性能优化,

文章目录 1.内核调试手段&#xff1a;debugfs.h中api建立目录/sys/kernel/debug2.性能优化&#xff1a;裸磁盘无法使用&#xff0c;一般都刷文件系统。驱动加上要考虑磁盘io&#xff0c;内存占用&#xff0c;cpu使用情况3.Valgrind内存泄漏排查案例&#xff1a;4.cpu瓶颈&#…

ArrayList的深拷贝与浅拷贝

1、深拷贝 通过以下代码进行理解 import java.util.ArrayList; import java.util.List;public class Demo {public static void main(String[] args) {List<Integer> c new ArrayList<>();c.add(1);c.add(2);c.add(3);List<Integer> c1 new ArrayList<…

部署Discuz论坛项目

DIscuz 是由 PHP 语言开发的一款开源社交论坛项目。运行在典型的LNMP/LAMP 环境中。 安装MySQL数据库5.7 主机名IP地址操作系统硬件配置discuz-db192.168.226.128CentOS 7-mini-20092 Core/4G Memory 修改主机名用来自己识别 hostnamectl set-hostname discuz-db #重连远程…

海外仓管理优化策略:花更少的钱,收获更大的收益

海外仓成本确实越来越高了。 仓储成本和人力成本几乎占据了海外仓经营成本的一大部分&#xff0c;这严重的影响了海外仓企业的盈利能力。如果你正打算开设海外仓业务或者已经在经营海外仓业务&#xff0c;那这个问题一定不能忽视&#xff0c;毕竟成本越高&#xff0c;就意味着你…

中北机械有限公司将参加2024长三角快递物流供应链与技术装备展览会

参展企业介绍 浙江中北机械有限公司总部位于浙江杭州&#xff0c;生产基地位于浙江桐乡。是一家有着十几年金属制品及仓储物流设施设备生产经验&#xff0c;专业设计、生产、制造各类物流钢制托盘&#xff0c;物流手推车&#xff0c;仓储货架及门店展架&#xff0c;宣传展架等物…

力扣HOT100 - 198. 打家劫舍

解题思路&#xff1a; 动态规划 class Solution {public int rob(int[] nums) {int len nums.length;if (nums null || len 0) return 0;if (len 1) return nums[0];int[] dp new int[len];dp[0] nums[0];dp[1] Math.max(nums[0], nums[1]);for (int i 2; i < len;…

zookeeper集群部署以及zookeeper原理

文章目录 简介工作原理特性官网地址准备节点准备环境准备JAVA主机映射 部署 简介 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服…

宝塔纯净版 7.6.0版本无需手机登录 [稳定版本/推荐]

下载地址&#xff1a;宝塔纯净版 7.6.0版本无需手机登录.zip 宝塔纯净版介绍 无需手机登录&#xff1a;不再有手机登录提示&#xff0c;或按照提示输入任意手机号密码即可模拟绑定&#xff1b; 安全&#xff1a;剥离了所有与宝塔官方的通信、上报、下发&#xff1b;并且不与…

Vue Excel 文件流导出乱码快速解决方案

今日在开发一个导出功能&#xff0c;原本一个非常简单的功能&#xff0c;却没想里面藏了陷阱&#xff01; 背景 前端导出的文件流乱码&#xff0c;此时确定非后端问题&#xff08;可以在postman导出是否正常来判断&#xff09;。 前端导出&#xff1a; 后端正常数据&#xf…