【C++】多态 (上)

在实际生活中我们也经常见到多态的例子,多态就是不同的对象完成同一个行为时会产生不同的状态,比如成人和儿童购票就是不一样的,多态是可以基于继承的,我们本篇博客的多态就是基于继承的,下面我们先看一个简单例子

cpp 复制代码
class person {
public:
	virtual void BuyTicket() {
		cout << "成人 全价" << endl;
	}
};
class children :public person {
public:
	virtual void BuyTicket() {
		cout << "儿童 半价" << endl;
	}
};
void func(person&p) {
	p.BuyTicket();
}
int main() {
	person s1;
	children s2;
	func(s1);
	func(s2);
	/*person* p1 = new person;
	person* p2 = new children;
	p1->BuyTicket();
	p2->BuyTicket();*/
	return 0;
}

可以看到,虽然这些指针或引用都是父类的,但是产生了不同的结果,恰巧这也是发生多态的一个条件
上面的代码只是一个样例,那么构成多态需要哪些条件呢?

1,虚函数的重写 ,重写也叫覆盖。重写也要满足条件:必须是父子类中的两个虚函数,两个虚函数有三同(参数,返回值,函数名)

2,需要通过父类的指针或引用去调用虚函数,这也就是我上边为什么会那么写
当然了,虚函数重写也是有特殊情况的

第一种叫做协变,意思是虚函数的返回值可以不同,但返回值必须是父子类关系的指针或者引用,比如

第二种是析构名字的特殊处理,什么意思呢?我们先看下面这种情况

这样的结果不对呀,我们new了一个children,为什么它只析构了person的那一部分,这会造成内存泄漏啊。我们想让析构形成多态,那就还差一个条件,构成虚函数的重写,于是我们加上virtual就可以了。

那你可能会说,不对呀,不是要三同吗?函数名也不同啊,我们上篇博客说过,析构函数名进行了特殊处理,都改成了destructor()。

下一种其实也不算是特殊情况,而就是一种形式上的特殊:就是如果父类函数写上virtual,子类不写的话也构成多态,这也说明了一个情况就是重写是函数的实现重写,声明不重写
那么下面我们来区分一下这三个概念:重载、重写(覆盖)、隐藏(重定义)

重载:两个函数在同一作用域,函数名要相同,参数要不同

重写:1.两个函数分别在基类和派生类的作用域2.函数名,参数,返回值都必须相同(协变除外)3.两个函数必须是虚函数

隐藏:1.两个函数分别在基类和派生类的作用域2.函数名相同3.两个基类和派生类的同名函数不构成重写就是重定义
下面是两个有关的关键字,final和override
如果我们要实现一个不能被继承 的类,有两种方式,一种是父类的构造函数私有化 ,这样就无法构建出一个父类对象,另一种就是这个类用final修饰,表示这个类是最终类,不能被继承

除此之外,final还可以修饰虚函数,使它不能被重写

override就是帮助检查重写有无问题,有问题会报错,没问题就直接过

下面有一道较为复杂的题目

cpp 复制代码
class A {
public:
	virtual void func(int val = 1) {
		cout << "A->" << val << endl;
	}
	virtual void test() { func(); }
};

class B :public A {
public:
	void func(int v = 0) {
		cout << "B->" << v << endl;
	}
};
int main() {
	B* p = new B;
	p->test();
	return 0;
}

从主函数开始,p调的test是A继承下来的,那么test的this是A*,func又构成重写(参数类型一样就可以,跟形参名无关),又是父亲指针去调用,就构成多态调用,重写又只是实现重写,声明并不重写,所以缺省值还是1

相关推荐
2401_8654396310 分钟前
CSS中隐藏元素的多重技巧与应用场景
开发语言·前端·javascript
雁迟25 分钟前
第六章:for 循环与 while 循环语句
开发语言·r语言
故事和你9128 分钟前
洛谷-【图论2-2】最短路1
开发语言·数据结构·c++·算法·动态规划·图论
csbysj202036 分钟前
Git 工作流程
开发语言
杰之行42 分钟前
Fast-DDS 接收数据完整时序分析
c++·人工智能
johnrui1 小时前
JUC之AQS
java·开发语言·jvm
沫璃染墨1 小时前
红黑树完全指南:从核心原理到插入验证全实现
开发语言·c++·算法
yu85939581 小时前
基于 QT5.7.0 的八线激光雷达点云聚类实现
开发语言·qt·聚类
号码认证服务1 小时前
客户看到来电显示公司名会更愿意接听吗?企业号码认证提升ROI
服务器·网络·c++·经验分享·智能手机·云计算·php
yoyo_zzm1 小时前
汇编到PHP:五大编程语言核心特性全解析
开发语言·汇编·php