继承——C++第二大特性

news2024/11/20 4:50:20

目录

一、概念及定义

1、概念

2、定义

 (2)方式

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

二、父类子类赋值转换

三、继承中的作用域

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

 六、继承与静态成员

七、复杂的菱形继承及菱形虚拟继承

八、归纳


一、概念及定义

1、概念

继承是类层次设计的复用

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	string _name="sunlang";
	int _age=21;
};
class Student :public Person
{
protected:
	int _number;
};
class Teacher :public Person
{
protected:
	int _teacher_number;
};
int main()
{
	Student s;
	Teacher t;
	s.Print();
	t.Print();
	return 0;
}

继承父类Person之后,成员函数、成员变量都会成为子类的一部分。还是挺牛批的!

2、定义

(1)格式

 (2)方式

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

类成员/继承方式

public继承

protected继承

private继承

基类的public成员

派生类的public成员

派生类的protected 成员

派生类的private 成员

基类的protected 成员

派生类的protected 成员

派生类的protected 成员

派生类的private 成员

基类的private成员

在派生类中不可见

在派生类中不可见

在派生类中不可见

给我好好听课:

第一,基类的私有成员被继承到了派生类中,语法上限制派生类对象在类里类外都不能去访问它。

第二,protected说明基类成员不能在类外被访问,但能在派生类中访问。

第三,class默认继承方式是private,struct默认继承方式是public

第四,常用public继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

class Person
{
public:
	void Print()
	{
		cout << _name << endl;
		cout << _age << endl;

	}
protected:
	string _name="sunlang";
private:
	int _age=21;
};
class Student :private Person//错误
{
protected:
	int _number=200700131;
};
int main()
{
	Student s;
	s.Print();
	return 0;
}

二、父类子类赋值转换

派生类对象可以赋值给基类的对象、基类的指针、基类的引用,俗称称甩刀手切割。

 基类对象不能赋值给派生类对象噢,宝宝~

基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或引用。

#include<iostream>
using namespace std;
class Person
{
protected:
	string _name;
	string _sex;
	int _age;
};
class Student :public Person
{
public:
	int _No;
};
void Test()
{
	Student sobj;
	//派生类对象可以赋值给基类的对象、指针、引用
	Person pobj = sobj;
	Person* ppobj = &sobj;
	Person& rpobj = sobj;
	//基类对象不能赋值给派生类
	//sobj = pobj;
	//基类的指针可以通过强制类型转换赋值给派生类的指针
	Student* ps1 = (Student*)(&pobj);
	ps1->_No = 10;
}

三、继承中的作用域

1、子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义,可以使用基类::基类成员显示访问

2、成员函数只需要函数名相同就构成隐藏

3、实际开发中不要定义同名成员,这是C++的缺陷啊,哥哥

class Person
{
protected:
	string _name = "小李子";
	int _num = 8848;
};
class Student :public Person
{
public:
	void Print()
	{
		cout << _name << endl;
		cout << Person::_num << endl;
		cout << _num << endl;
	}
protected:
	int _num = 9999;
};
//B中的func和A中的func不构成重载,因为不在同一作用域
//B中的func和A中的func构成隐藏,成员函数满足函数名相同就构成隐藏
class A
{
public:
	void func()
	{
		cout << "func()" << endl;
	}
};
class B:public A
{
public:
	void func(int i)
	{
		A::func();
		cout << "func(int i)" << endl;
	}
};
int main()
{
	Student s;
	s.Print();
	cout << endl;
	B b;
	b.func(1);
	return 0;

}

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

1、派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。

2、派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的那一部分拷贝初始化

3、派生类的operator=必须要调用基类的operator=完成基类的复制

4、派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员,保证派生类对象先清理派生类成员再清理基类成员

5、派生类对象初始化先调用基类构造再调用派生类构造

6、派生类对象清理先调用派生类析构再调用基类析构

7、父类析构函数不加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系

总结:

子类构造函数原则:调用父类构造函数初始化继承父类成员

自己再初始化自己的成员,析构、拷贝构造、复制重载也类似

class Person
{
public:
	Person(const char* name = "peter")
		:_name(name)
	{
		cout << "Person()" << endl;
	}
	Person(const Person& p)
		:_name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}
	Person& operator=(const Person& p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
		{
			_name = p._name;
		}
		return* this;
	}
	~Person()
	{
		cout << "~Person()" << endl;
	}
protected:
	string _name;
};
class Student :public Person
{
public:
	Student(const char* name, int num)
		:Person(name)
		, _num(num)
	{
		cout << "Student(const Student& s)" << endl;
	}
	Student(const Student& s)
		:Person(s)
		, _num(s._num)
	{
		cout << "Student(const Student&s)" << endl;
	}
	Student& operator=(const Student& s)
	{
		cout << "Student&operator=(const Student&s)" << endl;
		if (this != &s)
		{
			Person::operator=(s);
			_num = s._num;
		}
		return* this;
	}
	~Student()
	{
		cout << "~Student()" << endl;
	}
protected:
	int _num;
};
void Test()
{
	Student s1("jack", 18);
	Student s2(s1);
	Student s3("rose", 17);
	s1 = s3;
}
int main()
{
	Test();
	return 0;
}

 六、继承与静态成员

基类定义了static静态成员,只有一个static成员实例

class Person
{
public:
	Person()
	{
		++_count;
	}
protected:
	string _name;
public:
	static int _count;
};
int Person::_count = 0;
class Student :public Person
{
protected:
	int _stuNum;
};
class Graduate :public Student
{
protected:
	string _seminarCourse;
};
void TestPerson()
{
	Student s1;
	Student s2;
	Student s3;
	Graduate s4;
	cout << " 人数 :" << Person::_count << endl;
	Student::_count = 0;
	cout << " 人数 :" << Person::_count << endl;
}
int main()
{
	TestPerson();
	return 0;
}

七、复杂的菱形继承及菱形虚拟继承

菱型继承是多继承的一种特殊情况

 

class Person
{
public:
	string _name;
};
class Student :public Person
{
protected:
	int _num;
};
class Teacher :public Person
{
protected:
	int _id;
};
class Assistant :public Student, public Teacher
{
protected:
	string _majorCourse;
};
void Test()
{
	Assistant a;
	a._name = "sunlang";
	//显示指定访问哪个父类的成员可以解决二义性问题
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";
}
int main()
{
	Test();
	return 0;
}

虚拟继承可以解决菱形继承的二义性和数据冗余的问题

class Person
{
public:
	string _name;
};
class Student :virtual public Person
{
protected:
	int _num;
};
class Teacher :virtual public Person
{
protected:
	int _id;
};
class Assistant :public Student, public Teacher
{
protected:
	string _majorCourse;
};
void Test()
{
	Assistant a;
	a._name = "sunlang";
	//显示指定访问哪个父类的成员可以解决二义性问题
	a.Student::_name = "xxx";
	a.Teacher::_name = "yyy";
}
int main()
{
	Test();
	return 0;
}

虚拟继承的原理:

(234条消息) C++虚继承的概念_crystal_avast的博客-CSDN博客_c++的虚继承icon-default.png?t=M85Bhttps://blog.csdn.net/crystal_avast/article/details/7678704

八、归纳

1、一定不要设计菱形继承

2、多继承是缺陷

3、组合

public继承是is-a的关系,每个派生类对象都是一个基类对象

组合是has-a的关系,每个B对象中都有一个A对象

优先使用组合

白箱复用:耦合度高

黑箱复用:耦合度低

代码案例:

组合

class Tire
{
protected:
	string _brand = "sun";
	size_t _size = 89;
};
class Car
{
protected:
	string _colour = "白色";
	string _num = "赣B1234";
	Tire _t;
};

继承

class Car
{
protected:
	string _colour = "白色";
	string _num = "赣B1234";
};
class BMW :public Car
{
public:
	void Drive()
	{
		cout << "好车" << endl;
	}
};
class Bez:public Car
{
public:
	void Drive()
	{
		cout << "快车" << endl;
	}
};

下次见……

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

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

相关文章

C语言——每周刷题题集(第一周)

前言 做题可以更好地巩固所学知识&#xff0c;并加深对于知识点的理解。下面题目均来自牛客网入门编程练习题。 第一题: BC8 十六进制转十进制 描述&#xff1a; BoBo写了一个十六进制整数ABCDEF&#xff0c;他问KiKi对应的十进制整数是多少。 输入描述&#xff1a; 无 …

基于自注意力的生成对抗归因网络的交通流缺失数据修复

文章信息《Missing Data Repairs for Traffic Flow With Self-Attention Generative Adversarial Imputation Net》是2022年7月发表在期刊IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTA TION SYSTEMS上的一篇文章。摘要随着传感器技术的快速发展&#xff0c;由多个空间分布的传…

2023我为什么建议你学Python?

前言 最近有一位读者准备实习开始找工作&#xff0c;来跟我交流他目前找工作遇到的一些情况&#xff1a; “我被找工作弄得满头包&#xff0c;觉得好像自己学的专业很没有市场&#xff0c;也没有很好的大公司背书&#xff0c;根本没有和 HR 谈薪资的底气。 他最近撒简历发现…

Java IO流

一、IO的概念 Java IO&#xff1a;Java IO即Java 输入输出系统。不管我们编写何种应用&#xff0c;都难免和各种输入输出相关的媒介打交道&#xff0c;其实和媒介进行IO的过程是十分复杂的&#xff0c;这要考虑的因素特别多&#xff0c;比如我们要考虑和哪种媒介进行IO&#x…

react进阶用法完全指南

React调用回调函数&#xff0c;正确设置this指向的三种方法 通过bind this.increment this.increment.bind(this);通过箭头函数 <button onClick{this.multi}>点我*10</button> multi () > {this.setState({count: this.state.count * 10}) }箭头函数包裹 …

[附源码]Python计算机毕业设计大学生学科竞赛管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

【特征选择】时变正弦和 V 形传递函数 (BMPA-TVSinV) 的新型二元海洋捕食者算法附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

CSC7136B

CSC7136B是一款高效率低待机功耗原边反馈小功率 电源 AC/DC 驱动 电路&#xff0c;无 需光耦、TL431 及相关器件。CSC7136B采用开关频率调制和初级电流峰值振幅&#xff08; FM 和 AM &#xff09;多模式工作技术&#xff0c;保证了全负载和线性范围内的较高的转换效率。恒压模…

无法安装人脸检测dlib库的解决方法

1. 引言 dlib 库是一个用来人脸关键点检测的 Python 库&#xff0c;但因为其是 C 编写&#xff08;或需要 C编译&#xff1f;&#xff09;&#xff0c;使得在安装时可能会遇到各种各样问题。笔者在安装时遇到问题后&#xff0c;搜索了一些博客&#xff0c;看到了一些解决方法&…

基于Python+Mysql实现(WinForm)书店销售管理管理子系统【100010028】

书店销售管理管理子系统 一、设 计 总 说 明 现在社会随着计算机技术迅速发展与技术的逐渐成熟&#xff0c;信息技术已经使人们的生活发生深刻的变化。生活中的各种服务系统也使人们在生活中的联系日常销售活动方式发生了很大的变化&#xff0c;让效率较低的手工操作成为过去…

年网络安全观察报告 地域分布

执行摘要 从 1987 年 9 月 14 日&#xff0c;中国向世界发出第一封电子邮件 到如今&#xff0c;中国的互联网发展已过去整整 31 个年头。从消费互联、产业互联到万物互联&#xff0c;互联网正在加速改变我们的交流方式和交易方式&#xff0c;一次次 004.重塑了国家的经济形态和…

Java单例模式的写法及作用介绍

在创建型设计模式中&#xff0c;我们第一个学习的是单例模式&#xff08;Singleton Pattern&#xff09;&#xff0c;这是设计模式中最简单的模式之一。 单例是什么意思呢&#xff1f; 单例就是单实例的意思&#xff0c;即在系统全局&#xff0c;一个类只创建一个对象&#x…

友嘉银行坎坷的云原生之路

随着数字化浪潮的来临&#xff0c;云原生技术越来越火。云原生技术的持续更新&#xff0c;无一不在催促传统行业重塑业务体系以及产业生态的转型升级。说到云原生&#xff0c;目前已被认为是云计算最重要的发展方向&#xff0c;它拥有更优雅的架构、更灵活的调度、更完善的治理…

QT—常用窗口部件

一、QLabel 新建一个QWidget项目&#xff0c;设置基类为QWidget 1.显示文本 调用setText函数编辑要显示的文本&#xff0c;传入一个const QString类型的参数 例如&#xff1a; ui->TxtLabel->setText("Label文本&#xff0c;12345678"); 其中TxtLabel是一…

web大作业 web前端课程设计 web前端课程设计代码 web课程设计 HTML网页制作代码

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

【Android Room 库基础入门】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录一、前言二、Room 主要组件三、Room 基础入门3.1 引入 Room 库到项目3.2 Room 使用示例3.2.1 定义数据实体类3.3.2 定义数据访问对象&#xff08;DAO&#xff09;3.3…

如何成为一名IT咨询顾问?

咨询顾问这个工作&#xff0c;很多人都很羡慕&#xff0c;在别人看来咨询顾问的工作时间自由&#xff0c;可以到处出差和旅游&#xff0c;能够认识企业各种层面的人&#xff0c;见多识广。实际情况真的这么轻松吗&#xff1f;什么样的人适合做咨询顾问&#xff1f;做咨询顾问需…

《计算机网络》2022年期末试卷

《计算机网络》期末试卷2022年A卷

synchronized 关键字

文章目录一、synchronized 的特性互斥可重入二、 synchronized 使用示例三、 java标准库的线程安全类四、 死锁可重入死锁相互争夺锁哲学家就餐问题死锁的四个必要条件一、synchronized 的特性 互斥 synchronized 会起到互斥效果, 某个线程执行到某个对象的 synchronized 中时…

亚马逊、ebay测评自养号新手应该要怎么做?

如今很多的跨境卖家开始在深入了解测评自养号这块&#xff0c;都想在运营上减低一些成本&#xff0c;多增加一些利润。对于整个测评工作来说&#xff0c;测评技术可谓是非常核心的一个环节&#xff0c;多学习&#xff0c;不要浮躁&#xff0c;这样才能让我们不断提高自己的测评…