C++ 类之间的纵向关系-继承

news2024/11/28 14:37:41

目录

继承的基本概念

定义

使用方法

 内存空间

继承下构造·析构执行的顺序

构造函数

继承的基本概念

定义

被继承的类叫做基类(父类),继承的类叫派生类(子类),在子类类名后面加:继承方式 父类

class CFather {

};
class CSon :public CFather {

};

使用方法

通过继承关系,子列可以使用父类的成员。如果子类和父类有同名的成员,默认使用子类的成员,如果想要使用父类成员,需要在成员名前加上类名::用于显式的指定区分。

父类:

class CFather {
public:
	int m_fa;

	int m_money;



	void funFather() {
		cout << __FUNCTION__ << endl;
	}

	void fun() {
		cout << "CFather::fun" << endl;
	}
};

子类:

class CSon :public CFather {
public:
	int m_money;

	CSon() {
		m_fa = 1;
		CFather::m_money = 100;//父类的m_money
		CSon::m_money = 200;//子类的m_money
		m_money = 300; //默认使用的是子类的成员

	}
	void funSon() {
		cout << m_fa << endl;
		funFather();
	}

	void fun() {
		cout << "CSon::fun" << endl;
	}

};

测试:

创建一个子类对象,通过子类成员函数调用父类的成员属性,在子类中的构造函数中也可给父类的成员属性初始化值。当子类与父类有同名成员时,可以通过类名作用域来区分,默认使用的是当前类对象的成员。

int main()
{
	CSon son;

	son.funSon();

	cout << son.CFather::m_money << endl; //100
	cout << son.CSon::m_money << endl; //300

	son.fun();//默认子类
	son.CFather::fun();//父类
	son.CSon::fun();//子类

	return 0;
}

 内存空间

子类继承父类,相当于父类的成员包含到自己的类里,所以定义子类对象所占用的空间大小除了子类自身的成员,还包括父类的成员。成员在内存空间分布为:先父类成员后子类成员,而每个类中的成员分布与在类中声明的顺序一致。

 内存大小:

	cout << sizeof(CFather) << "    " << sizeof(CSon) << endl;  //8   12

 内存分配:

	CSon son;

	cout << &son << endl;//00D4FC6C
	cout << &son.m_fa << "    " << &son.CFather::m_money << "    " << &son.m_money << endl;//00D4FC6C    00D4FC70    00D4FC74

继承下构造·析构执行的顺序

构造函数

执行的顺序:父构造->子构造(函数体代码)

构造顺序说明:在子类创建对象的时候,会先跳转到子类的构造函数(注意这里并不是直接先执行父类的构造函数),先执行构造的初始化参数列表,初始化顺序看在类中声明的先后顺序(等同于成员在内存排布的先后顺序),由于父类在前,子类成员在后,所以先初始化父类成员,调用父类的构造函数。初始化完毕后,再回到子类初始化参数列表,按照顺序继续初始化其他成员,所有成员初始化完毕后,再执行子类自己的构造函数体代码。

  注意1:在初始化列表中会默认调用父类的无参构造初始化父类成员,如果父类只有带参数的构造,在子类的初始化列表中必须显示的指定父类构造进行初始化。这有点像之前说的组合关系形式。

  注意2:不能在子类构造函数的初始化参数列表中直接对父类中的成员属性初始化,更不能在子类构造函数的函数体代码中初始化(实际是赋值操作),因为如果在创建对象时要创建父类对象,那么将不会调用子类的构造函数,而父类中又没有构造函数。

默认调用父类无参构造:

class CFather {
public:
	int m_fa;
	CFather() :m_fa(3) {
		cout << __FUNCTION__ << endl;
	}

};

class CSon :public CFather {
public:
	int m_son;
	CSon():/*CFather(),编译器会默认调用父类的无参构造*/m_son(1)/*,m_fa(0)*/ {
		m_fa = 0;//赋值操作
		cout << __FUNCTION__ << endl;
	}
};

手动显示指定调用父类的构造:

class CFather {
public:
	int m_fa;
	CFather() :m_fa(3) {
		cout << __FUNCTION__ << endl;
	}

};

class CSon :public CFather {
public:
	int m_son;
	CSon() :CFather(),/* 手动显示指定调用父类的构造 */m_son(1) {
		cout << __FUNCTION__ << endl;
	}
};

父类中没有无参构造时,必须手动显式指定出来:

class CFather {
public:
	int m_fa;
	CFather() :m_fa(3) {
		cout << __FUNCTION__ << endl;
	}
};

class CSon :public CFather {
public:
	int m_son;
	CSon(int a) :CFather(a), m_son(1) {

	}
};

如果父类中存在多个构造函数,想使用带参数的构造函数,也需要手动指定,否则会调用无参的父类构造了

class CFather {
public:
	int m_fa;
	CFather() :m_fa(3) {
		cout << __FUNCTION__ << endl;
	}
	CFather(int a) :m_fa(a) {
		cout << __FUNCTION__ << endl;
	}
};

class CSon :public CFather {
public:
	int m_son;
	CSon(int a) :CFather(a), m_son(1) {

	}
};

析构函数

执行的顺序:子析构->父析构

析构顺序说明:子类对象的生命周期结束后,因为是子类所以自动调用子类析构,当析构执行完了,才会回收对象分配的空间(和构造的顺序相反),当然这个空间包含创建的父类成员,那么回收父类匿名对象前,会自动调用父类的析构,再回收父类对象本身。如果是new出来的子类对象,同理。

class CTest {
public:
	int m_tst;
public:
	CTest(int a) :m_tst(a) {
		cout << __FUNCTION__ << endl;
	}

	~CTest() {
		cout << __FUNCTION__ << endl;
	}

};

class CFather {
public:
	int m_fa;
public:
	CFather(int a) :m_fa(a) {
		cout << __FUNCTION__ << endl;
	}
	~CFather() {
		cout << __FUNCTION__ << endl;
	}
};

class CSon :public CFather {
public:
	CTest tst;
	int m_son;
public:
	CSon(int a) :tst(a + 2), CFather(a + 1), m_son(a) {
		cout << __FUNCTION__ << endl;
	}
	~CSon() {
		cout << __FUNCTION__ << endl;
	}


};
int main() {
	CSon son(1);





	return 0;
}

 上三行为构造函数,下三行为析构函数,构造函数和析构函数执行的顺序相反。

 继承的优点

  可以将一些功能比较相似的类中公共的成员,抽离出来形成一个类,即是一个父类,这些子类继承父类,可以使用父类成员,公共的成员在父类中只维护一份代码即可,如果要添加新的公共的成员,只需要在父类中添加一份即可。增加新的子类公共的成员不必再重复写了,增加了程序代码的复用性、扩展性、灵活性,减少代码冗余

class CPeople {
public:
	int m_money;
	CPeople():m_money(100){}
	void cost(int n) {
		cout << __FUNCTION__ << endl;
		m_money -= n;
	}

	void play() {
		cout << "溜溜弯" << endl;
	}

	void drink() {//如果增加公共的功能,属性,只需要在父类中增加一份即可
		cout << "喝饮料" << endl;

	}
};

class CWhite : public CPeople{

public:
	//CWhite():m_money(100){}

	void eat() {
		cout << "吃牛排" << endl;
	}


};

class CYellow : public CPeople {
public:

	void eat() {
		cout << "小烧烤" << endl;
	}

};

class CBlack : public CPeople {
public:

	void eat() {
		cout << "西瓜炸鸡" << endl;
	}

};

class CBlue : public CPeople {
public:

	void eat() {
		cout << "吃另一个阿凡达" << endl;
	}
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript概述一

1.JavaScript介绍 1.1 前端三要素 HTML:超文本标记语言&#xff0c;是一种使用标签&#xff08;标记&#xff09;描述网页中的视图内容的语言;CSS&#xff1a;层叠样式表&#xff0c;主要用于美化web页面外观,决定了网页中的视图效果&#xff1b;JavaScript&#xff1a;用于网…

PHP快速入门07-Cookie与Session的说明与使用

文章目录前言一、关于Cookie和Session1.1 Cookie1.2 Session二、Cookie和Session的使用2.1 Cookie的使用例子2.2 Session的使用例子总结前言 本文已收录于PHP全栈系列专栏&#xff1a;PHP快速入门与实战 Cookie和Session是一个Web开发几乎不可避免的东西&#xff0c;是网站开发…

Java入坑之Numbers Strings

目录 一、Lambda表达式 1.1简介 1.2使用场景 1.3Lambda表达式的使用条件 1.4Lambda表达式的语法 1.5Lambda表达式的精简 二、方法引用 2.1基本概念 2.2使用条件 2.3语法格式 2.4静态方法引用 2.5特定对象的实例方法 2.6构造函数的方法引用 三、包装类 3.1概念 3…

K_A28_004 基于STM32等单片机驱动SI4432对发SI4432实现数据传输 OLED显示

K_A28_004 基于STM32等单片机驱动SI4432对发SI4432实现数据传输 OLED显示所有资源导航一、资源说明二、基本参数参数引脚说明三、驱动说明时序:对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RCSI4432无线模块1.2、STM32F103C8T6SI4432无线模块五、基础知识学习与相关…

基于tensorflow和tensorflow-quantum的量子机器学习环境搭建, Mac环境下

量子神经网络&#xff08;Quantum neural networks, QNN&#xff09;及其变体量子卷积神经网络&#xff08;Quantum convolutional networks, QCNN&#xff09;&#xff0c;在内存和速度方面都有着高效的优势&#xff0c;能将经典向量由n维编码到log2^n个量子位&#xff0c;同时…

分子生物学 第四章 DNA的生物合成

文章目录第四章 DNA的生物合成第一节 DNA复制的一般特征1 DNA的半保留复制2 DNA的双向复制3 DNA的半不连续复制第二节 DNA复制的酶学1 DNA聚合酶1.1 原核生物DNA pol1.1.1 DNA pol I1.2 DNA pol II1.3 DNA pol III1.4 其它的DNA pol1.2 真核生物DNA聚合酶1.2.1 DNA pol α\alph…

深度学习基础入门篇[五]:交叉熵损失函数、MSE、CTC损失适用于字识别语音等序列问题、Balanced L1 Loss适用于目标检测

1.交叉熵损失函数 在物理学中&#xff0c;“熵”被用来表示热力学系统所呈现的无序程度。香农将这一概念引入信息论领域&#xff0c;提出了“信息熵”概念&#xff0c;通过对数函数来测量信息的不确定性。交叉熵&#xff08;cross entropy&#xff09;是信息论中的重要概念&am…

ITIL社群的内容及作用

官方网站 www.itilzj.com 文档资料: wenku.itilzj.com ITIL是全球范围内最为流行的IT服务管理框架之一&#xff0c;它能够帮助企业提高IT服务质量&#xff0c;提升业务价值。无论你是IT行业的从业者还是对ITIL感兴趣的人士&#xff0c;ITIL之家社群都将为你提供有价值的知识和经…

非关系型数据库---Redis安装与基本使用

一、数据库类型 关系数据库管理系统(RDBMS)非关系数据库管理系统(NoSQL) 按照预先设置的组织机构&#xff0c;将数据存储在物理介质上(即&#xff1a;硬盘上) 数据之间可以做无关联操作 (例如: 多表查询&#xff0c;嵌套查询&#xff0c;外键等) 主流的RDBMS软件&#xff1a;My…

java io流 概念 详解

IO流 当需要把内存中的数据存储到持久化设备上这个动作称为输出&#xff08;写&#xff09;Output操作。 当把持久设备上的数据读取到内存中的这个动作称为输入&#xff08;读&#xff09;Input操作。 因此我们把这种输入和输出动作称为IO操作。 学习目标: 一、文件类&#x…

张程伟:从开源项目到企业级数据库,云和恩墨 MogDB Uqbar 的技术探索与实践...

导语4月8日下午&#xff0c;为期两天的第十二届数据技术嘉年华&#xff08;DTC 2023&#xff09;在北京新云南皇冠假日酒店圆满落下帷幕。大会以“开源融合数字化——引领数据技术发展&#xff0c;释放数据要素价值”为主题&#xff0c;汇聚产学研各界精英到场交流。作为大会的…

电蚊拍欧盟CE认证EMC+LVD测试

电蚊拍&#xff08;Mosquito&#xff09;&#xff0c;主要由高频振荡电路、三倍压整流电路和高压电击网DW三部分组成。工作中&#xff0c;经升压电路在双层电网间产生1850V直流左右的高压电&#xff0c;两电网间的静电场有较强的吸附力&#xff0c;当蚊蝇等害虫接近电网时&…

系统集成路由器OSPF动态、综合路由配置

实验任务&#xff1a;动态路由协议RIP、OSPF协议的内容和特点动态路由RIP、OSPF实验&#xff0c;建立拓扑pc1>>R1>>R2>>R3>>pc2&#xff0c;使pc1与pc2能相互通信&#xff0c;并配置PC端静默接口。熟悉配置vlan间路由技术&#xff1a;多层交换机虚拟接…

落地“旅游+”数字赋能:实现智慧旅游协同创新发展

经济的蓬勃发展&#xff0c;与之带来的是消费水平的不断提升&#xff0c;旅行已经成为我们日常生活中不可缺少的一项。在过去三年间&#xff0c;我们由于或这或那的原因&#xff0c;并无法真正实现一场说走就走的旅程。大家在过去的三年算是憋狠了&#xff0c;所以在今年&#…

计算专题(小计算题)

考点&#xff1a; 1.沟通渠道的总量为 n*(n-1)/2&#xff0c;其中 n 代表干系人的数量。 2.决策树计算/自制和外购决策-----EMV。 3.盈亏平衡计算。&#xff08;刚好不亏也不赚&#xff09; 【案例】假设某IT服务企业&#xff0c;其固定成本为30万元&#xff0c;每项服务的变…

用于测试FDIA在现实约束下可行性的FDIA建模框架(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 信息通信技术的发展和智能设备的引入使电力系统逐渐演变为电力信息物理系统&#xff0c;而信息层与物理层之间的深度耦合也加剧…

HashMap死循环详解

目录 一、数据插入原理 二、导致死循环的原因 三、解决方案 一、数据插入原理 由于JDK1.7中&#xff0c;HashMap的底层存储结构采用的是数组链表的方法 插入数据时候采用的是头插法 二、导致死循环的原因 此时线程T1&#xff0c;T2节点同时指向A节点&#xff0c;同时线程T1…

Spring Boot 整合 Swagger 教程详解

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

小白必看,吐血整理Facebook新手指南(二)

上篇文章咱们讲了关于FB广告的类型&#xff0c;今天咱们再来详细讲下如何设置FB广告、注意事项以及如何借助强大的工具&#xff08;SaleSmartly、ss客服&#xff09;监控广告效果、承接广告流量。话不多说&#xff0c;直接上干货选择你的目标 首先&#xff0c;前往您的广告管理…

虚拟化服务器和普通服务器的区别

随着云计算技术的快速普及&#xff0c;虚拟化技术作为其中的一项核心技术&#xff0c;也越来越受到了企业和个人用户的关注。虚拟化服务器相较于传统的物理服务器&#xff0c;具备更高的灵活性和可扩展性&#xff0c;但同时也存在一些不足之处。那么虚拟化服务器的优缺点有哪些…