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++知识库 -> Cukor丘克说C++进阶03(下) 2021-08-21 -> 正文阅读

[C++知识库]Cukor丘克说C++进阶03(下) 2021-08-21

类的继承(后续内容)

继承的传递性

内容很简单,就是A继承给B,然后B又继承给C,·······

这种情况就是继承的传递,就像是先有的爷爷,然后有的爸爸,再然后才有现在的你一样,然后你可能还会有下一代,然后下一代又有下下一代等。

在C++中,类的继承也是如此,但是在程序中避免出现这样的情况,要不然类会显得很臃肿。直接上代码看看。

#include<iostream>
using namespace std;

//先封装一个A类当作爷爷类
class A
{
public:
	A(string name,int age):name(name),age(age)
	{
		cout << "A" << endl;
	}
protected:
	string name;
	int age;
};

//在封装一个B类当作爸爸类
class B:public A
{
public:
	//A类的属性和行为放到这个地方

	//调用B类的构造函数的时候先会调用A类的构造函数
	B(string name, int age, int money) :A(name, age), money(money)
	{
		cout << "B" << endl;
	}
protected:
	int money;	//B类自己的属性
};

//再封装一个C类当作第三代
class C:public B
{
public:
	//B类的属性和行为放到这里,C类中也有A类的属性和行为,但C类的构造函数不用调用A类的构造函数,在B类中已经调用了
	C(string name, int age, int money, int faceScore) :B(name, age, money), faceScore(faceScore)
	{
		cout << "C" << endl;
	}
protected:
	int faceScore;	//C类自己的属性
};

int main()
{
	//创建一个C类对象
	C c("小明", 20, 10000, 80);
	/*
		输出结果:A
			   	 B
				 C
	*/
	return 0;
}

小结:

  • 祖父类继承下去后,后面的类都有祖父了的属性和行为
  • 创建子类对象的时候,先调用最原始的类的构造函数,然后逐层调用对应的构造函数,直到调用子类的构造函数结束,子类对象才创建好
  • 显式调用构造函数只在最相关联系的两个类之间

多继承

在现实生活中,儿子是由爸爸和妈妈共同生的,那么这个儿子就同时继承了他爸爸和他妈妈的东西。

在C++中,子类也可以继承多个父类的属性和行为,然后这个子类就同时拥有了这些父类中的属性和行为。

一般写法:

/*
多继承的时候,继承方式可以不同
class 子类名:继承方式 第一个父类名,继承方式 第二个父类名,······,继承方式 第n个父类名
{
使用什么继承方式就把父类的属性和行为放到哪个限定词下面
子类的内部写东西,那就是派生
子类的内部不写东西,那就是继承
public:

protected:

};


*/

写多继承时的注意点:

  • 继承方式可以不同,也可以相同
  • 子类可以继承任意多个父类
  • 继承顺序决定调用构造函数的顺序
  • 继承顺序决定调用析构函数的顺序(和构造函数相反的顺序)

代码测试:

#include<iostream>
using namespace std;

class A
{
public:
	A(string name) :name_A(name)
	{
		cout << "A" << endl;
	}
protected:
	string name_A;
};

class B
{
public:
	B(string name) :name_B(name)
	{
		cout << "B" << endl;
	}
protected:
	string name_B;
};

class C
{
public:
	C(string name) :name_C(name)
	{
		cout << "C" << endl;
	}
protected:
	string name_C;
};

//构造函数的调用顺序之和继承顺序有关
class D : protected B, public A, private C
{
public:
	D(string name_A, string name_B, string name_C, string name_D) :
		A(name_A), B(name_B), C(name_C)
	{
		//D类自己本身的属性可以在初始化参数列表中进行初始化,也可以在构造函数内部进行初始化
		this->name_D = name_D;
		cout << "D" << endl;
	}
protected:
	string name_D;
};

int main()
{
	//创建子类对象
	D d("A", "B", "C", "D");
	/*
		输出结果:
		B
		A
		C
		D
	*/
	return 0;
}

继承中的特殊成员

简单回顾一下,静态是用staitc修饰的东西,属于整个类,不属于某个对象。静态数据成员在类外初始化,静态成员函数中没有this指针。

通过继承之后,父类和子类共有这个静态属性或行为。

举个简单的例子

父亲有一把砍柴刀,父亲已经用到生锈了,然后他的儿子继承了这把刀,但是这把刀并不是新的刀,还是那把已经生锈了的刀。然后他们共用这把生锈的刀。

静态数据成员

静态数据成员就是static修饰类中数据成员的成员,必须在类中声明,在类外初始化。

直接看代码:

#include<iostream>
using namespace std;

class Father
{
public:
	//静态数据成员也是受权限限定的,为了能类外访问,所以写成public限定
	static int knife;	//在类中声明,在类外初始化

	//写一个无参构造函数
	Father()
	{
		//每次调用Father的构造函数的时候knife做自增运算
		knife++;
	}
};

//类外初始化的时候去掉static修饰词,加类名限定
int Father::knife = 0;

//Son公有继承Father
class Son :public Father
{
public:
	//Farther的属性和行为放到这个地方
	//没有写构造函数,但是存在一个默认的构造函数,也存在这个默认构造函数隐式调用父类的构造函数
};

int main()
{
	//创建父类对象
	Father father;
	cout << "父类无对象访问:" << Father::knife << endl;	//1
	cout << "父类对象访问:" << father.knife << endl;		//1
	//创建子类对象
	Son son;
	cout << "父类无对象访问:" << Father::knife << endl;	//2
	cout << "父类对象访问:" << father.knife << endl;		//2
	cout << "子类无对象访问:" << Son::knife << endl;		//2
	cout << "子类对象访问:" << son.knife << endl;			//2
	/*
	输出结果:
	父类无对象访问:1
	父类对象访问:1
	父类无对象访问:2
	父类对象访问:2
	子类无对象访问:2
	子类对象访问:2
	*/
	return 0;
}

小结:

  • 静态数据成员在类中声明在类外初始化,类外初始化的时候去掉static修饰词,加类名限定
  • 静态数据成员也受权限限定
  • 继承下来的静态数据成员,父类和子类共用

静态成员函数

静态成员函数就是在类中使用static修饰的成员函数,可以在类中实现也可以在类外实现,静态成员函数没有this指针,因为this不知道代指谁。

那继承之后会是怎样,直接看代码

#include<iostream>
using namespace std;

class Father
{
public:
	//静态成员函数
	static void print()
	{
		cout << "Father类中的静态成员函数" << endl;
		//this->faceScore = 100;	//错误,在静态成员函数中没有this指针
		//静态成员函数中不能直接访问非静态数据成员
		//只有两种方式:传参和在这个函数中创建对象,通过对象去访问才行
		Father Cukor;
		Cukor.faceScore = 100;	//正确
		Cukor.money++;
		cout << Cukor.faceScore << "\t"<<Cukor.money<<endl;
		//faceScore = 99;	错误,因为faceScore不知道是谁的
	}
protected:
	int faceScore;
	static int money;
};

int Father::money = 1000;

//公有继承
class Son :public Father
{
public:
	//父类的属性和行为放到这里

protected:

};

int main()
{
	Father father;
	Son son;
	father.print();
	son.print();
	son.print();
	father.print();
	/*
	输出结果:
	Father类中的静态成员函数
	100     1001
	Father类中的静态成员函数
	100     1002
	Father类中的静态成员函数
	100     1003
	Father类中的静态成员函数
	100     1004
	*/
	return 0;
}

小结:

  • 静态成员函数可以在类中实现也可以在类外实现
  • 静态成员函数没有this指针,因为this不知道代指谁。
  • 静态成员函数中不能直接访问非静态数据成员
  • 静态成员函数中访问类中的数据成员,只有两种方式:传参和在这个函数中创建对象,通过对象去访问才行
  • 静态成员函数继承给子类后,父类和子类共用这个静态成员函数
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-22 13:21:43  更:2021-08-22 13:23:56 
 
开发: 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/27 4:59:05-

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