【C++】:多态的实现

希望文章能对你有所帮助,有不足的地方请在评论区留言指正,一起交流学习!

1.多态

1.1 什么是多态

不同的对象(派生类和基类)执行同一个行为\事件产生的结果是不一样的;是多种状态的。

同一个接口,不同的实现;

即使用不同的派生对象 来调用同一个接口会产生不同的状态。 且函数接口继承于父类,父类也是可以调用的。

如下图,Person 为人,Student 继承了Person 的派生类,二者均调用一个函数,产生了多种状态,这种情况是怎么实现的呢

1.2 构成多态的条件

  1. 通过父类指针或者引用的调用虚函数

  2. 调用的函数必须是虚函数,且子类对虚函数完成重写。
    调用区别

  3. 多态调用: 被调函数,看指向的对象

2.普通调用看 当前对象的类型。

虚函数

在成员函数前面加上关键字 virtual , 并且基类的成员函数和派生类的成员函数的**返回值、函数名字以及参数列表(类型、 顺序、数量)相同,**参数列表相同不包含形参的名字啊。

特例

  1. 派生类的函数可以不加 virtual,也可以实现虚函数。(建议在使用的时候加上,好辨认)
  2. 协变: 虚函数的返回值 可以是父类和子类的引用或者指针,当然自身的父子引用以及其他父子类的引用和指针均可以,父类的引用必须是父类,子类的引用必须是子类。(完全没有必要)

为什么派生类中的函数可以不加 virtual

因为在基类中的函数已经加入 virtual ,表明此函数就是 虚函数,派生类的继承继承这个函数的性质,在不加 virtual 的时候也是虚函数。

重写是对函数体重新构建 ,其他的保持三同,重写还叫做是覆盖

插入一个知识点

重写(覆盖)

  1. 重写,复用基类虚函数的函数签名和返回值**,** 提供函数更加具体的实现。 在编译层面上是通过虚函数表关联的**,** 被视为用同一个函数的不同形态**。同一接口的不同行为。**

  2. 在派生类中的函数名字 和基类相同 的成员函数,不是重写就是重定义

注:函数标签就是函数名、参数列表和成员函数的 const限定符。

重定义(隐藏)

本质 :派生类 中只要存在与基类同名的函数 ,就会屏蔽基类 中所有同名函数

总结:

重写是 "同一个函数的不同实现"(非新函数),依赖虚函数实现多态;

重定义是 "同名的不同函数"(新函数),仅存在名称巧合,无多态支持。

1.3.析构函数的多态(重点)

C++的类中将析构函数的函数名 统一处理 为 destructor,为了是让析构函数也构成多态。

但是特殊情况, 会造成内存泄漏

由于是指针或者引用调用,在这里实现多态,便可以实现

总结

  1. 为了构成多态析构函数的名字 统一为destructor()
  2. 子类不加virtual也算是析构函数的特权了,
  3. 基类析构函数 建议直接加入 virtual

1.4.C++11的关键字 override 和 final (类不被继承)

final 不让 函数重写 、不让类被继承,final表示类为最终的类,不可被继承

override 帮助派生类检测函数重新是否完成,没有重新,报错

将BuyTicket(),删除末尾的 t ,然后就不是函数重新,override检测还是是否符合三同。

设计不想被继承的类

1.私有 的成员函数在基类 中是不可见的,就是不可以使用,使用就会报错的。

2.派生类的构造函数必须调用基类构造函数

将父类的构造函数放入私有中,

cpp 复制代码
class A
{
public:
	static A CreatObj()
	{
		return A();
	}
	int a = 1;
private:
	A() 
	{}
};
class B : public A
{
public:
private:

};

将父类的析构函数放入私有中,

cpp 复制代码
class A
{
public:
	static A*  CreatObj()
	{
		return new A();
	}
	static void destroyObj(A* obj)
	{
		delete obj;
	}
	int a = 1;
private:
	A() 
	{}
	~A()
	{}
};
class B : public A
{
public:
private:

};
cpp 复制代码
A* obj = A::CreatObj(); // 创建对象
	A::destroyObj(obj);

我试了 :仅设析构私有可阻止继承,但基类自身的对象无法正常销毁(栈对象无法创建、堆对象无法 delete),因此实际中很少单独这么用,就是老老实实用私有构造函数防止继承吧

1.5.总结

  1. 多态针对是成员函数(非静态(引用指针调用))
  2. 虚函数的继承,派生类继承的是接口的使用权,目的是为了重写。
  3. 实现继承(普通的继承)派生类继承了基类函数,可以使用函数,继承的是函数的实
相关推荐
flysh0517 小时前
关于C#编程中的async / await关键字
开发语言·c#
好好学操作系统17 小时前
flash_attn ImportError undefined symbol:
开发语言·python
CCPC不拿奖不改名17 小时前
面向对象编程:继承与多态+面试习题
开发语言·数据结构·python·学习·面试·职场和发展
chen_22717 小时前
动态桌面方案
c++·qt·ffmpeg·kanzi
liulilittle17 小时前
OPENPPP2 Code Analysis Three
网络·c++·网络协议·信息与通信·通信
꧁Q༒ོγ꧂17 小时前
算法详解(一)--算法系列开篇:什么是算法?
开发语言·c++·算法
橘颂TA17 小时前
【剑斩OFFER】算法的暴力美学——力扣:1047 题:删除字符串中的所有相邻重复项
c++·算法·leetcode·职场和发展·结构于算法
早日退休!!!17 小时前
GCC与LLVM编译器深度解析:核心原理与差异对比(小白向)
c++·编辑器
星火开发设计17 小时前
Python数元组完全指南:从基础到实战
开发语言·windows·python·学习·知识·tuple