【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. 实现继承(普通的继承)派生类继承了基类函数,可以使用函数,继承的是函数的实
相关推荐
EndingCoder13 小时前
案例研究:从 JavaScript 迁移到 TypeScript
开发语言·前端·javascript·性能优化·typescript
Yyyyy123jsjs13 小时前
如何通过免费的外汇API轻松获取实时汇率数据
开发语言·python
白露与泡影13 小时前
2026版Java架构师面试题及答案整理汇总
java·开发语言
历程里程碑14 小时前
滑动窗口---- 无重复字符的最长子串
java·数据结构·c++·python·算法·leetcode·django
一个天蝎座 白勺 程序猿14 小时前
KingbaseES查询逻辑优化深度解析:从子查询到语义优化的全链路实践
开发语言·数据库·kingbasees·金仓数据库
skywalker_1115 小时前
Java中异常
java·开发语言·异常
2501_9403152615 小时前
航电oj:首字母变大写
开发语言·c++·算法
没有天赋那就反复15 小时前
JAVA 静态方法
java·开发语言
Thomas_YXQ15 小时前
Unity3D在ios平台下内存的优化详解
开发语言·macos·ios·性能优化·cocoa