IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 教授先生的c++学习成长之路(笔记2)继承与派生 -> 正文阅读

[C++知识库]教授先生的c++学习成长之路(笔记2)继承与派生

1.继承和派生 public:private:protected

?

?

?

看了那么多图片,有点乱吧?简单来说就为了提高类的可重用性,具有相同属性,相同功能的函数不用再重新写到新的一个类里面,只需使用继承与派生, 基类也称父类,派生类也称子类。

看第一张图,person里的姓名性别年龄籍贯这些和新的类student的部分属性重复了,不需要在student中重复写。把person作为基类,student继承积累的属性。 student类也同样获得person的属性。

而在继承和派生过程中同时出现了3种方式,分别是?public:private:protected

我们首先来看看他们的定义

(非常重要,看不懂时重复理解)
public:可以被该类中的函数、子类的函数、友元函数访问,也可以由该类的对象访问;
protected:可以被该类中的函数、子类的函数、友元函数访问,但不可以由该类的对象访问;
private:可以被该类中的函数、友元函数访问,但不可以由子类的函数、该类的对象、访问。

?以上这张图片大致是本节内容的精髓

记住:基类中的私有成员不允许派生

比方说有一个基类(父类)A,子类B,B是A的private类,则A中所有的private:类内的数据成员和成员函数都不能被直接访问(不允许继承)。

在C++类中,我们通常使用? 指针? ?.(点的方式) 成员函数? ?这三种方式直接访问数据成员和成员函数

比如

#include<iostream>
#include<cstring>
using namespace std; 
struct A
{

string name;
string getname()
{
 return name;
}

};
int main()
{
	A a,c;
	A *b;//b是一个 自定义类形的指针  
	b=new A; //开辟一个新的A类空间,并使指针b指向这个新开辟的A类的空间
	string name_1,name_2,name_3;
	cin>>name_1;
	a.name=name_1;//1.通过 点 的方式(访问)给对象的名字属性赋值 
	cin>>name_2;
	b->name=name_2;//2.通过 指针 的方式(访问)给对象的名字属性赋值 
	cin>>name_3;
	c.name=name_3;
//	以下是输出
	cout<<a.name<<endl;//1.通过 点 的方式(访问)显示对象的属性--名字
	cout<<b->name<<endl;//2.通过 指针 的方式(访问)显示对象的属性--名字
	cout<<c.getname()<<endl;//3.先通过点的方式访问从而间接利用 成员函数 的方式(访问)显示对象的属性--名字 
	
	
}

我们暂且不讨论指针在继承中的使用,访问通过? ?1?对象+点.的方式2 通过 对象+点.访问子类的成员函数从而间接访问基类的数据成员或者成员函数

4.14那个图我教大家我自己的一个记忆方法:

1.private的继承方式 :基类(包括所有继承方式)中的private都是不允许访问(继承), 而在private的继承方式中其他的(public和protected)都变成private 。

2.public的继承方式 :尊重原则,除了privated原来是怎么样就怎么样,不改变。public->public.? protected->protected

3.protected的继承方式:除了privated,强行保护,public->protected? .? protected->protected

然后结合定义自己理解一下

(非常重要,看不懂时重复理解)
public:可以被该类中的函数、子类的函数、友元函数访问,也可以由该类的对象访问;
protected:可以被该类中的函数、子类的函数、友元函数访问,但不可以由该类的对象访问;
private:可以被该类中的函数、友元函数访问,但不可以由子类的函数、该类的对象、访问。

举个例子

?第一个报错 不能显示出x,因为x是私有成员,不可以被继承,第二个报错是因为y是基类中是protected成员,通过public继承到子类仍然为protected类,但是protected类不可以由该类的对象访问;

?如图第一个报错改成Showxy( )后,通过子类成员函数去访问基类的成员函数,这是允许的。

第二个报错若想修改,可以通过对 子类增加一个给Y赋值的成员函数,对obj.成员函数 调用重而实现赋值。

2.派生类的构造函数

这个总参数表包含了给基类构造函数传参用的,也包含了派生类中新增的成员的传参?

我们来看下面这个例子,把3个参传给基类,剩下1个参留给自己?

3.类的组合

继承练习1

①声明并实现一个名为Person的基类,Person类有保护数据成员name(姓名,string类型)、sex(性别,char类型,'M'表示男,'F'表示女)。以及有参构造函数,将姓名、性别设置为给定的参数;成员函数print,输出姓名和性别。????????????????????????????????????????????????????????????????????????????????????????????????

②从Person类派生出Student类,Student类有私有数据成员status(状态,string类型),表示年级(FRESHMAN、SOPHOMORE、JUNIOR、SENIOR),表示大一、大二、大三、大四学生。以及有参构造函数,将姓名、性别、状态设置为给定的参数;成员函数print,print函数输出姓名、性别和状态。
③定义MyDate类,它包含私有数据成员year、month和day以及带默认参数的有参构造函数,年、月、日的默认参数值分别为1900、1、1;成员函数print,输出年、月、日。
④从Person类派生出Employee类,Employee类有保护数据成员salary(薪水,int类型)、dateHired(雇佣日期),dataHired的类型是MyDate。以及有参构造函数,将姓名、性别、薪水和雇佣日期设置为给定的参数;成员函数print,输出姓名、性别、薪水和雇佣日期。
⑤从Employee类派生出Faculty类,Faculty类有私有数据成员rank(级别,string类型),有(PROFESSOR、ASSOCIATE_PROFESSOR、LECTURER),表示教授、副教授、讲师。以及有参构造函数,将姓名、性别、薪水、雇佣日期和级别设置为给定的参数;成员函数print,输出姓名、性别、薪水、雇佣日期和级别。
⑥从Employee类派生出Staff类,Staff类有私有数据成员headship(职务,string类型),有(PRESIDENT、DEAN、DEPARTMENT_CHAIRMAN),表示校长、院长、系主任。以及有参构造函数,将姓名、性别、薪水、雇佣日期和职务设置为给定的参数;成员函数print,输出姓名、性别、薪水、雇佣日期和职务。????????????????????????????????????????????????????????????????????????????????????????????????

?????????????????????????????????????????????????????????????????????????????????????????????????

输入输出示例

逐个输入:????????????????????????????????????????????????????????????????????????????????????????????????

Person对象的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Student的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Data的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Employee的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Faculty的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Staff的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

其中雇佣日期都使用相同的日期,所以构造一个对象即可????????????????????????????????????????????????????????????????????????????????????????????????

????????????????????????????????????????????????????????????????????????????????????????????????

输入输出
示例 1
ZhangSan
M
LiSi
F
FRESHMAN
2012
10
31
WangWu
M
5000
LiuLiu
M
10000
PROFESSOR
QianQi
M
8000
DEPARTMENT_CHAIRMAN
Name:ZhangSan, Sex:M
Name:LiSi, Sex:F
FRESHMAN
Name:WangWu, Sex:M
Salary:5000, Hire date:2012-10-31
Name:LiuLiu, Sex:M
Salary:10000, Hire date:2012-10-31
PROFESSOR
Name:QianQi, Sex:M
Salary:8000, Hire date:2012-10-31
DEPART

?我们来看一道值得深度思考的题目

继承练习1

①声明并实现一个名为Person的基类,Person类有保护数据成员name(姓名,string类型)、sex(性别,char类型,'M'表示男,'F'表示女)。以及有参构造函数,将姓名、性别设置为给定的参数;成员函数print,输出姓名和性别。????????????????????????????????????????????????????????????????????????????????????????????????

②从Person类派生出Student类,Student类有私有数据成员status(状态,string类型),表示年级(FRESHMAN、SOPHOMORE、JUNIOR、SENIOR),表示大一、大二、大三、大四学生。以及有参构造函数,将姓名、性别、状态设置为给定的参数;成员函数print,print函数输出姓名、性别和状态。
③定义MyDate类,它包含私有数据成员year、month和day以及带默认参数的有参构造函数,年、月、日的默认参数值分别为1900、1、1;成员函数print,输出年、月、日。
④从Person类派生出Employee类,Employee类有保护数据成员salary(薪水,int类型)、dateHired(雇佣日期),dataHired的类型是MyDate。以及有参构造函数,将姓名、性别、薪水和雇佣日期设置为给定的参数;成员函数print,输出姓名、性别、薪水和雇佣日期。
⑤从Employee类派生出Faculty类,Faculty类有私有数据成员rank(级别,string类型),有(PROFESSOR、ASSOCIATE_PROFESSOR、LECTURER),表示教授、副教授、讲师。以及有参构造函数,将姓名、性别、薪水、雇佣日期和级别设置为给定的参数;成员函数print,输出姓名、性别、薪水、雇佣日期和级别。
⑥从Employee类派生出Staff类,Staff类有私有数据成员headship(职务,string类型),有(PRESIDENT、DEAN、DEPARTMENT_CHAIRMAN),表示校长、院长、系主任。以及有参构造函数,将姓名、性别、薪水、雇佣日期和职务设置为给定的参数;成员函数print,输出姓名、性别、薪水、雇佣日期和职务。????????????????????????????????????????????????????????????????????????????????????????????????

?????????????????????????????????????????????????????????????????????????????????????????????????

输入输出示例

逐个输入:????????????????????????????????????????????????????????????????????????????????????????????????

Person对象的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Student的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Data的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Employee的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Faculty的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

Staff的构造信息????????????????????????????????????????????????????????????????????????????????????????????????

其中雇佣日期都使用相同的日期,所以构造一个对象即可????????????????????????????????????????????????????????????????????????????????????????????????

????????????????????????????????????????????????????????????????????????????????????????????????

输入输出
示例 1
ZhangSan
M
LiSi
F
FRESHMAN
2012
10
31
WangWu
M
5000
LiuLiu
M
10000
PROFESSOR
QianQi
M
8000
DEPARTMENT_CHAIRMAN
Name:ZhangSan, Sex:M
Name:LiSi, Sex:F
FRESHMAN
Name:WangWu, Sex:M
Salary:5000, Hire date:2012-10-31
Name:LiuLiu, Sex:M
Salary:10000, Hire date:2012-10-31
PROFESSOR
Name:QianQi, Sex:M
Salary:8000, Hire date:2012-10-31
DEPART

#include<iostream>
using namespace std;
class Person
{
	public:
		
		void print1()
		{
			cout<<"Name:"<<Name<<", Sex:"<<sex<<endl;
		}
		Person(string Name_,char sex_)
		{
			Name=Name_;
			sex=sex_;
		}
		protected:
		string Name;
		char sex;	
};

class Student:public Person
{
	public:
		
		Student(string Name_,char sex_,string status_):Person(Name_,sex_)
		{
			
			status=status_;
		}
		void print2()
	{
		print1();
		cout<<status<<endl;
	}
	
	private:
		     string status;
};

class MyDate
{
 public:
		void print3()
		{
			cout<<year<<"-"<<month<<"-"<<day<<endl;
		}
		MyDate(int year_,int month_,int day_)
		{   year=year_;
		    month=month_;
		    day=day_;
			
		}
	private:
		 int year;
		 int month;
		 int day;		 
};

class Employee:public Person
{	

    public:
		void print4()
		{
			print1();
			cout<<"Salary:"<<salary;
			cout<<", Hire date:";dateHired.print3();
		}
		Employee(string Name_,char sex_,int salary_,int year_,int month_,int day_):dateHired( year_, month_,day_),Person(Name_,sex_)
		{
			salary=salary_;
		}
	protected:
		int salary;
		MyDate dateHired;
		
};
class Faculty:public Employee 
{
	public:
		Faculty(string Name_,char sex_,int salary_,string rank_,int year_,int month_,int day_):
		Employee(Name_,sex_,salary_,year_,month_,day_)
		{
			rank=rank_;
		}
		void print5()
		{
			 print4();cout<<rank<<endl;
		}
	private:
		string rank;
		string Name;
};
class Staff:public Employee
{
	public:
		Staff(string Name_,char sex_,int salary_,string headship_,int year_,int month_,int day_):Employee(Name_,sex_,salary_,year_,month_,day_)
			{
				headship=headship_;
			}
			void print6()
		{
			 print4();cout<<headship<<endl;
		}
		
	private: 
	string headship;
};
int main()
{
	string name1,name2,status2,name3,rank1,headship1,name4;
	char sex1,sex2,sex3,sex4;
	int year,month,day,salary1,salary2;
	cin>>name1>>sex1;
	Person a1(name1,sex1);
	
	cin>>name2>>sex2>>status2;
	Student a2(name2,sex2,status2);
	
	cin>>year>>month>>day>>name3>>sex3>>salary1;
	Employee a3(name3,sex3,salary1,year,month,day);
	
	cin>>name3>>sex3>>salary1>>rank1;
	Faculty a4(name3,sex3,salary1,rank1,year,month,day);
	cin>>name4>>sex4>>salary2>>headship1;
	Staff a5(name4,sex4,salary2,headship1,year,month,day);

	a1.print1();a2.print2();a3.print4();	a4.print5(); a5.print6();
}

?这道题目涉及到类的组合,派生的构造函数,继承方式等多个知识点糅合在一起,有一定难道,建议读者认真花时间思考,是一道非常不错的题目,自己读代码。

值得提的是类的组合的格式如下图

?4.继承中的同名函数

在派生函数中的函数如果和基类中的函数同名,派生(子)函数中同名函数优先级更高一些,若非要表示基类中的函数则 基类名::成员名

5.在派生函数中更改访问声明(不改变基类的权限),

?数据成员也可以用访问声明

6.连续继承

?我们仔细看上面一张图,这是一个连续继承的图示

首先基类中的 a和 两个成员函数都被私有继承到派生类Devided1中,变成私有的,然后再连续私有继承到Devided2中,因为私有成员不可被继承,所以在Devided2中a和 基类中的两个成员函数就消失了。紧接着的是Devided1中的protected型的b和 public型 的两个成员函数都被私有继承到

Devided2中。

这便是连续继承。

7.多重继承

解决多重继承中的二义性问题?

?

继承中派生类的构造函数,析构函数也具有先进后出,后进先出的

接下来请重点看一看这个

在声明定义类 Derived的对象 obj之前,要先调用这个对象的基类Base1,Base2,但是这两个基类它又是Base类的派生类,所以,在调用这个Base1或者Base2之前,又要调用2次他们的基类Base,因此顺序就是Base->Base1->Base->Base2->Derived

8.虚基类

因为有相同基类,在构造时会出现同名函数但却代表不同含义,我们称之为二义性,它也会影响最终结果,为了解决这个问题,我们提出了一个新的概念————虚基类,这个类能实现共同基类中相同的函数名或者属性只会出现1次?因此顺序就是Base->Base1->Base2->Derived

?顺序就是Base->Base1->Base2->Derived

?

?

?虚基类和普通基类的主要区别在于 两个直接基类Base1,Base2继承方式前面+ virtual,在 Derived构造函数定义是要带上虚基类的形参列表并且赋值 例如? ?":Base(sa)"

?1.所有直接或间接派生类都要调用虚基类构造函数。

2.由最远派生类调用虚基类构造函数,其他基类调用被忽略。

Base->Base1->Base2->Derived遵循以上规则

先在主函数中找到obj对象的传参,找到 Derived类的构造函数,优先调用虚基类的构造函数

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Base->?Derived

其次到Base1->Base2 声明顺序的这个两个构造函数,并且在这两个构造函数中忽略Base虚基类的调用? ? 在Base与?Derived中间插入Base1->Base2->

即:??Base->Base1->Base2->Derived

#include<iostream>
using namespace std;
class base
{
	public:
	string name;
	int age;
	void show1()
	{
		cout<<"name:"<<name<<endl;
		cout<<"age:"<<age<<endl;
	}
};
class derived:public base
{
	public:
	string sex;
	void show2()
	{
		cout<<"name:"<<name<<endl;
		cout<<"age:"<<age<<endl;
		cout<<"sex:"<<sex<<endl;
	}
	 
};
int main()
{
	base person1;
	derived person2;
	person2.age=18;
	person2.name="xiaoming";
	person2.sex="man";
	person2.show2();
	person1=person2;//这个是全文代码的核心,公有继承派生类的属性比基类的属性多,
	//赋值的时候可以把派生类的对象直接赋给基类的对象,但基类的对象属性仅仅是基类本身的属性
	//派生类新增的属性在基类中不显示。(因为基类没有这些属性) 
	person1.show1();

	
 } 

?

?

?公有继承派生类的属性比基类的属性多,赋值的时候可以把派生类的对象直接赋给基类的对象,但基类的对象属性仅仅是基类本身的属性,派生类新增的属性在基类中不显示。(因为基类没有这些属性) 除了直接赋值,还有引用,指针等赋值方式,赋值结果相同

以下是我选择题出现的错误,以下均为正确答案,可以自行理解

1.构造函数和析构函数不能被派生类继承。

2.派生类中包含了基类中的成员,它是对基类定义的扩充和延续,是对基类定义的进一步具体化,而不是基类的子集。

3.友元函数能访问类的私有成员

4.基类的构造函数和析构函数不能被派生类继承.

5.类与类之间的友元关系不可以继承

6.友元函数破坏了类的封装性和隐藏性

7.友元函数不是类的成员函数

?这题选择D,在建立一个派生类的对象时,先调用? 基类->成员对象类(其他类作为成员函数,类的组合)->派生类自身

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:22:52  更:2022-05-09 12:25:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/4 2:57:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码