C++类和对象(继承)

news2024/12/23 19:07:37

4.6继承

继承是面向对象三大特性之一

有些类与类之间存在特殊的关系,例如下图中:

我们发现,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。

这个时候我们就可以考虑利用继承的技术,减少重复代码

4.6.1继承的基本语法

//继承的好处:减少重复的代码。

//语法:class 子类 : 继承方式(public) 父类

//子类  也称为  派生类

//父类  也称为  基类 

#include<iostream>
using namespace std;
//普通实现界面

Jave页面
//class Jave
//{
//public:
//	void header()
//	{
//		cout << "首页、公开课、登录、注册...(公共头部)"<< endl;
//	}
//	void footer()
//	{
//		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
//	}
//	void left()
//	{
//		cout << "Jave、Python、C++、...(公共分类列表)" << endl;
//	}
//	void centent()
//	{
//		cout << "Jave学科视频" << endl;
//	}
//private:
//
//};
Python页面
//class Python
//{
//public:
//	void header()
//	{
//		cout << "首页、公开课、登录、注册...(公共头部)" << endl;
//	}
//	void footer()
//	{
//		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
//	}
//	void left()
//	{
//		cout << "Jave、Python、C++、...(公共分类列表)" << endl;
//	}
//	void centent()
//	{
//		cout << "Python学科视频" << endl;
//	}
//private:
//
//};
C++页面
//class CPP
//{
//public:
//	void header()
//	{
//		cout << "首页、公开课、登录、注册...(公共头部)" << endl;
//	}
//	void footer()
//	{
//		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
//	}
//	void left()
//	{
//		cout << "Jave、Python、C++、...(公共分类列表)" << endl;
//	}
//	void centent()
//	{
//		cout << "C++学科视频" << endl;
//	}
//private:
//
//};

//继承实现页面
//公共页面类
class BasePage
{
public:
	void header()
	{
		cout << "首页、公开课、登录、注册...(公共头部)"<< endl;
	}
	void footer()
	{
		cout << "帮助中心、交流合作、站内地图...(公共底部)" << endl;
	}
	void left()
	{
		cout << "Jave、Python、C++、...(公共分类列表)" << endl;
	}
private:
	
};
//继承的好处:减少重复的代码。
//语法:class 子类 : 继承方式(public) 父类
//子类  也称为  派生类
//父类  也称为  基类  
//Jave页面
class Jave : public BasePage//继承。
{
public:
	void centent()
	{
		cout << "Jave学科视频" << endl;
	}
};
//Python页面
class Python : public BasePage
{
public:
	void centent()
	{
		cout << "Python学科视频" << endl;
	}
};
//C++页面
class CPP : public BasePage
{
public:
	void centent()
	{
		cout << "C++学科视频" << endl;
	}
};

void test01()
{
	cout << "Jave下载视频页面如下:" << endl;
	Jave ja;//创建对象。
	ja.header();
	ja.footer();
	ja.left();
	ja.centent();
	cout << "-----------------------" << endl;
	cout << "Python下载视频页面如下:" << endl;
	Python py;//创建对象。
	py.header();
	py.footer();
	py.left();
	py.centent();
	cout << "-----------------------" << endl;
	cout << "C++下载视频页面如下:" << endl;
	CPP cpp;//创建对象。
	cpp.footer();
	cpp.left();
	cpp.centent();
	/*cout << "xxxxx" << endl;*/
}

int main()
{
	test01();

	system("pause");
	return 0;
}

总结:

继承的好处:可以减少重复的代码

class A : public B

A类称为子类 或 派生类

B类称为父类 或 基类

派生类中的成员,包含两大部分:

一类是从基类继承过来的,一类是自己增加的成员。

基类继承过过来的表现其共性,而新增的成员体现了其个性

4.6.2继承方式

继承的语法:class子类∶继承方式父类

继承方式一共有三种:

  1. 公共继承
  2. 保护继承
  3. 私有继承

 

#include<iostream>
using namespace std;
//继承方式
//公共继承
class Base1
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

class Son1 :public Base1
{
public:
	void func()
	{
		m_A = 10;//父类中的公共权限成员 到子类中依然是公共权限
		m_B = 10;//父类中的保护权限成员 到子类中依然是保护权限
		//m_C=10;//父类中私有权限成员  子类访问不到
	}
};

void test01()
{
	Son1 s1;
	s1.m_A = 100;
	//s1.m_B = 100;//到Son1中 m_B是保护权限  类外访问不到。
	cout <<"m_A=" <<s1.m_A<< endl;
}
//保护继承
class Base2
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

class Son2 :protected Base2
{
public:
	void func()
	{
		m_A = 100;//父类中的公共权限成员 到子类中依然是公共权限
		m_B = 100;//父类中的保护权限成员 到子类中依然是保护权限
		//m_C=100;//父类中私有权限成员  子类访问不到
	}
};

void test02()
{
	Son2 s2;
	//s2.m_A = 100;//在Son2中 m_A是保护权限,因此类外访问不到。
	//s2.m_B = 100;//在Son2中 m_B保护权限 不可以访问。
}

//私有继承
class Base3
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

class Son3 :private Base3
{
public:
	void func()
	{
		m_A = 100;//父类中的公共权限成员 到子类中依然是公共权限
		m_B = 100;//父类中的保护权限成员 到子类中依然是保护权限
		//m_C=100;//父类中私有权限成员  子类访问不到
	}
};

void test03()
{
	Son3 s3;
	//s3.m_A = 1000;//在Son3中 变为  私有成员  类外访问不到。
	//s3.m_B = 1000;//在Son3中 变为  私有成员  类外访问不到。
}
//孙子继承
class GrandSon3 :public Son3
{
public:
	void func()
	{
		//m_A = 1000;//到了Son3中 m_A变为私有,即使是儿子,也是访问不到的。
	}
};

int main()
{
	test01();

	system("pause");
	return 0;
}

4.6.3继承中对象模型

问题:从父类继承过来的成员,哪些属于子类对象中?

#include<iostream>
using namespace std;
//继承中的对象模型
class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

class Son :public Base
{
public:
	int m_D;
};
//利用开发人员命令提示工具查看对象模型
//跳转盘符 F:
//跳转文件路径 cd 具体路径下
// c1 /d1 reportSingleClassLayout类名 文件名
void test01()
{
	//在父类中所有非静态成员属性都会被子类继承下去
	//父类中私有成员属性 是被编译器给隐藏了,因此是访问不到,但是确实被继承下去了。
	cout << "size of son =" <<sizeof(Son) << endl;//16 = 4 x 4
}

int main()
{
	test01();

	system("pause");
	return 0;
}

结论:父类中私有成员也是被子类继承下去了,只是由编译器给隐藏后访问不到。

4.6.4继承中构造和析构顺序

子类继承父类后,当创建子类对象,也会调用父类的构造函数

问题:父类和子类的构造和析构顺序是谁先谁后?

#include<iostream>
using namespace std;
//继承中的构造和析构顺序
class Base
{
public:
	Base()
	{
		cout << "Base构造函数!" << endl;
	}
	~Base()
	{
		cout << "Base析构函数!" << endl;
	}
private:

};
class Son :public Base
{
public:
	Son()
	{
		cout << "Son构造函数!" << endl;
	}
	~Son()
	{
		cout << "Son析构函数!" << endl;
	}
};


void test01()
{
	//Base b;
	//继承中的构造和析构顺序如下:
	//先构造父类,在构造子类,析构的顺序和构造的顺序相反
	Son s;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

总结:继承中 先调用父类构造函数,再调用子类构造函数,析构顺序与构造相反。

4.6.5继承同名成员处理方式

问题:当子类与父类出现同名的成员,如何通过子类对象,访问到子类或父类中同名的数据呢?

  1. 访问子类同名成员直接访问即可
  2. 访问父类同名成员需要加作用域
#include<iostream>
using namespace std;
//继承中同名成员处理
class Base
{
public:
	Base()
	{
		m_A = 100;
	}
	void func()
	{
		cout << "Base - func()调用" << endl;
	}
	void func(int a)
	{
		cout << "Base - func(int a)调用" << endl;
	}
	int m_A;
private:

};

class Son :public Base
{
public:
	Son()
	{
		m_A = 200;
	}
	void func()
	{
		cout << "Son - func()调用" << endl;
	}
	int m_A;
private:

};

void test01()
{
	Son s;
	cout << "Son  下 m_A=" << s.m_A << endl;
	//如果通过子类对象  访问到父类中同名成员,需要加作用域
	cout << "Base 下 m_A=" << s.Base::m_A << endl;//添加父类的作用域
}
//同名成员函数处理
void test02()
{
	Son s;
	s.func();//直接调用 调用是子类中的同名成员。
	//如何调用到父类中同名成员函数?
	s.Base::func();
	//如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有的同名成员函数。
	//如果想访问到父类中被隐藏的同名成员含函数,需要加作用域
	s.Base::func(100);
}	

int main()
{
	test01();
	test02();

	system("pause");
	return 0;
}

总结:

1.子类对象可以直接访问到子类中同名成员

2.子类对象加作用域可以访问到父类同名成员

3.当子类与父类拥有同名的成员函数,子类会隐藏父类中同名成员函数,加作用域可以访问到父类中同名函数

4.6.6继承同名静态成员处理方式

问题:继承中同名的静态成员在子类对象上如何进行访问?

静态成员和非静态成员出现同名,处理方式—致

  1. 访问子类同名成员直接访问即可
  2. 访问父类同名成员需要加作用域
#include<iostream>
using namespace std;

class Base
{
public:
	static void func()
	{
		cout << "Base - static void func()调用" << endl;
	}
	static void func(int a)
	{
		cout << "Base - static void func(int a)调用" << endl;
	}
	static int m_A;//类内声明,内外初始化。
private:

};
int Base::m_A = 100;//类内声明,内外初始化。

class Son:public Base
{
public:

	static int m_A;//类内声明,内外初始化。
private:

};
int Son::m_A = 200;//类内声明,内外初始化。
//同名静态成员属性
void test01()
{
	//1、通过对象访问
	cout << "通过对象访问:" << endl;
	Son s;
	cout << "Son  下 m_A=" << s.m_A << endl;
	cout << "Base 下 m_A=" << s.Base::m_A << endl;
	//2、通过类名访问
	cout << "通过类名访问:" << endl;
	cout << "Son  下 m_A=" << Son::m_A << endl;
	//第一个::代表通过类名方式访问  第二个::代表访问父类作用域下
	cout << "Base 下 m_A=" << Son::Base::m_A << endl;
}
//同名静态成员函数
void test02()
{
	//1、通过对象访问
	cout << "通过对象访问:" << endl;
	Son s;
	s.func();
	s.Base::func();

	//2、通过类名访问
	cout << "通过类名访问:" << endl;
	Son::func();
	Son::Base::func();
	//子类出现和父类同名静态成员函数,也会隐藏父类中所有同名成员函数
	//如果想访问父类中被隐藏同名成员,需要加作用域。
	Son::Base::func(100);
}

int main()
{
	//test01();
	test02();

	system("pause");
	return 0;
}

总结:同名静态成员处理方式和非静态处理方式一样,只不过有两种访问的方式(通过对象和通过类名)。

4.6.7多继承语法

C++允许一个类继承多个类

语法:class子类∶继承方式  父类1,继承方式  父类2……

多继承可能会引发父类中有同名成员出现,需要加作用域区分

C++实际开发中不建议用多继承

#include<iostream>
using namespace std;
//多继承语法
class Base1
{
public:
	Base1()
	{
		m_A = 100;
	}
	int m_A;
private:

};

class Base2
{
public:
	Base2()
	{
		m_B = 200;
	}
	int m_A;
	int m_B;
private:

};
//子类  需要继承Base1和Base2
//语法:class 子类 :继承方式  父类1,继承方式 父类2  ...
class Son :public Base1, public Base2
{
public:
	Son()
	{
		m_C = 300;
		m_D = 400;
	}
	int m_C;
	int m_D;
};

void test01()
{
	Son s;
	cout << "size of Son = " <<sizeof(s)<< endl;
	//当父类中出现同门成员,需要加作用域区分
	cout << "Base1 下 m_A = " << s.Base1::m_A << endl;
	cout << "Base2 下 m_A = " << s.Base2::m_A << endl;
}

int main()
{
	test01();

	system("pause");
	return 0;
}

4.6.8菱形继承

菱形继承概念:

       两个派生类继承同一个基类

       又有某个类同时继承者两个派生类

       这种继承被称为菱形继承,或者钻石继承

典型的菱形继承案例:

菱形继承问题:

1.羊继承了动物的数据,驼同样继承了动物的数据,当草泥马使用数据时,就会产生二义性。

2.草泥马继承自动物的数据继承了两份,其实我们应该清楚,这份数据我们只需要一份就可以。

#include<iostream>
using namespace std;
//动物类
class Animal
{
public:
	int m_Age;
private:

};
//利用虚继承,解决菱形继承的问题
//继承之前,加上关键字 virtual 变为虚继承
//Animal类称为 虚基类
//羊类
class Sheep:virtual public Animal{};
//驼类
class Tuo :virtual public Animal{};
//羊驼类
class SheepTuo :public Sheep, public Tuo {};

void test01()
{
	SheepTuo st;
	st.Sheep::m_Age = 18;
	st.Tuo::m_Age = 20;
	//当菱形继承,两个父类拥有相同数据,需要加以作用域区分
	cout << "st.Sheep::m_Age=" << st.Sheep::m_Age << endl;
	cout << "st.Tuo::m_Age=" << st.Tuo::m_Age << endl;
	cout << "st.m_Age=" << st.m_Age << endl;
	//这份数据告诉我们知道,只有有一份就可以,菱形继承导致数据有两份,资源浪费
}

int main()
{
	test01();

	system("pause");
	return 0;
}

总结:

  1. 菱形继承带来的主要问题是子类继承两份相同的数据,导致资源浪费以及毫无意义
  2. 利用虚继承可以解决菱形继承问题

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

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

相关文章

阿里云PAIx达摩院GraphScope开源基于PyTorch的GPU加速分布式GNN框架

作者&#xff1a;艾宝乐 导读 近期阿里云机器学习平台 PAI 团队和达摩院 GraphScope 团队联合推出了面向 PyTorch 的 GPU 加速分布式 GNN 框架 GraphLearn-for-PyTorch(GLT) 。GLT 利用 GPU 的强大并行计算性能来加速图采样&#xff0c;并利用 UVA 来减少顶点和边特征的转换和…

Spring Security Oauth2.1 最新版 1.1.0 整合 gateway 完成授权认证(拥抱 springboot 3.1)

目录 背景 版本 Spring Boot 3.1 Spring Authorization Server 1.1.0官方文档 基础 spring security OAuth2.0 模块构成 授权方式 集成过程 官方demo 代码集成 依赖 授权服务AuthorizationServerConfig配置 重要组件 测试 查看授权服务配置 访问授权服务 授…

AB32VG1:SDK_AB53XX_V061(5)蓝牙BLE测试笔记

文章目录 1.配置工程&#xff0c;重新编译1.1替换链接库libbtstack_dm.a1.2 《config.h》打开编译开关1.3 在 Downloader 里面打开 BLE 开关 2.ABLink&#xff08;手机APP&#xff09;控制2.1 app下载2.2 安装后打开&#xff0c;搜索蓝牙Bluetrum&#xff1a;2.3 操作存储卡 3.…

深度学习应用篇-元学习[14]:基于优化的元学习-MAML模型、LEO模型、Reptile模型

【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍&#xff1a;【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化…

华为认证 | HCIP-Datacom-Core 考试大纲

01 考试概况 02 考试内容 HCIP-Datacom-Core Technology V1.0考试覆盖数据通信领域各场景通用核心知识&#xff0c;包括路由基础、OSPF、 IS-IS、BGP、路由和流量控制、以太网交换技术、组播、IPv6、网络安全、网络可靠性、网络服务与管理、 WLAN、网络解决方案。 ★路由基础 …

【MySQL 函数】:一文彻底搞懂 MySQL 函数(一)

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL字符串函数和数学函数的讲解✨ 目录 前言一、字符串函数二、数学函数三、总结 一、字符串函数 函数作用UPPER(列|字符串)将字符串每个字符转为大写LOWER(列|字符串)将字符串每个字符转为小写CONCAT(str1,str2,…

阿里云企业邮箱购买流程

阿里云企业邮箱购买流程&#xff0c;企业邮箱分为免费版、标准版、集团版和尊享版&#xff0c;阿里云百科分享企业邮箱版本区别&#xff0c;企业邮箱收费标准价格表&#xff0c;以及阿里企业邮箱详细购买流程&#xff1a; 目录 阿里云企业邮箱购买流程 一、阿里云账号注册及…

OpenAI 刚刚宣布了海量更新

OpenAI 刚刚宣布了海量更新&#xff0c;增加函数调用&#xff0c;支持更长上下文&#xff0c;价格更低&#xff01; ​新模型上架 1、gpt-4-0613 2、gpt-4-32k-0613 3、gpt-3.5-turbo-0613 4、gpt-3.5-turbo-16k 部分模型降价 1、text-embedding-ada-002&#xff1a;$0.00…

DevExpress WinForms功能区组件,让业务应用创建更轻松!(上)

DevExpress WinForms的Ribbon&#xff08;功能区&#xff09;组件灵感来自于Microsoft Office&#xff0c;并针对WinForms开发人员进行了优化&#xff0c;它可以帮助开发者轻松地模拟当今最流行的商业生产应用程序。 PS&#xff1a;DevExpress WinForm拥有180组件和UI库&#…

Linux安装SQLServer数据库

Linux安装SQLServer数据库 文章目录 Linux安装SQLServer数据库SQLServer是什么SQLServer的安装安装要求安装步骤安装配置安装命令行工具 SQLServer是什么 美国 Microsoft 公司推出的一种关系型数据库系统。SQL Server 是一个可扩展的、高性能的、为分布式客户机/服务器计算所设…

[PostgreSQL-16新特性之EXPLAIN的GENERIC_PLAN选项]

随着PostgreSQL-16beta1版本的发布&#xff0c;我们可以发现&#xff0c;对于我们时常使用的explain增加了一个GENERIC_PLAN选项。这个选项是允许了包含参数占位符的语句&#xff0c;如select * from tab01 where id$1;等等这种语句&#xff0c;让其生成不依赖于这些参数值的通…

两个HC-05蓝牙之间的配对

两个HC-05蓝牙之间的配对 文章目录 两个HC-05蓝牙之间的配对1.进入AT指令模式后&#xff0c;先确定是否为AT模式&#xff1a;2.获取模块A,B的地址3.将蓝牙A配置为主模式&#xff0c;将蓝牙B配置为从模式&#xff1a;4.设置模块通信波特率,蓝牙模块A和B的配置需要相同6.验证 买了…

目标检测数据集---玻璃瓶盖工业缺陷数据集

✨✨✨✨✨✨目标检测数据集✨✨✨✨✨✨ 本专栏提供各种场景的数据集,主要聚焦:工业缺陷检测数据集、小目标数据集、遥感数据集、红外小目标数据集,该专栏的数据集会在多个专栏进行验证,在多个数据集进行验证mAP涨点明显,尤其是小目标、遮挡物精度提升明显的数据集会在该…

儿童遗留监测成为「加分项」,多种技术路线「争夺战」一触即发

儿童遗留密闭车内&#xff0c;温度可以在短短15分钟内达到临界水平&#xff0c;从而可能导致中暑和死亡&#xff0c;尤其是当汽车在太阳底下暴晒。 按照Euro NCAP给出的指引&#xff0c;与车祸相比&#xff0c;儿童因车辆中暑而死亡的情况较少&#xff0c;但却是完全可以避免的…

计算机网络开荒4-网络层

文章目录 一、网络层概述1.1 路由转发1.2 建立连接1.3 网络服务类型 二、虚拟电路与数据报网络2.1 虚电路Virtual circuits VC网络2.1.1 VC 实现2.1.1 虚电路信令协议(signaling protocols) 2.2 数据报网络2.3 对比 三、Internet网络的网络层 IP协议3.1 IP分片3.1.1 最大传输单…

中创|数据中心集聚,算力企业环绕,郑州:力争打造中部最强数据中心集群

信息时代&#xff0c;算力就是生产力。从田间到车间、从陆地到天空&#xff0c;算力的应用已经在方方面面“大显身手”。不仅是在存储领域&#xff0c;在具体的应用服务领域&#xff0c;算力也无处不在。 手机支付、网上购物、精准导航、人脸识别……这些人们熟悉的生活场景&a…

如何在telnet连接的情况下下载上传文件

1.下载tftp文件 TFTP下载-TFTP正式版下载[电脑版]-华军软件园 2.选择自己PC机所在的IP 3.telnet登录到设备 4.上传下载 //上传&#xff1a; 从Clinet&#xff08;设备&#xff09;上传文件到Server&#xff08;PC机&#xff09;时&#xff0c; 使用下面的命令 tftp –p –…

cesium学习笔记

cesium入门笔记 一、下载源码&#xff0c;源码介绍二、html案例体验三、cesium中的类介绍1.它们分别是&#xff1a;2.四大类的完整演示代码&#xff1a; 四、cesium的坐标与转换五、相机系统介绍六、地图、地形的加载七、建筑体添加和使用八、空间数据加载1、加载数据2、对加载…

python中变量与字符串详解!!

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 初学者经常会遇到的困惑是&#xff0c;看书上或者是听课都懂…

数据库:mysqldump用法详解

目录 一、命令格式详解 1.1 语法格式 1.2 常用参数 1.3 完整参数 二、mysqldump常见的几个错误 2.1、提示命令未找到 -bash: mysqldump: 未找到命令 2.2、 the command line interface can be insecure 2.3、Gotpacket bigger than ‘max_allowed_packet‘ bytes 一、命令格式详…