【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. 实现继承(普通的继承)派生类继承了基类函数,可以使用函数,继承的是函数的实
相关推荐
盐真卿14 分钟前
python第八部分:高级特性(二)
java·开发语言
茉莉玫瑰花茶17 分钟前
C++ 17 详细特性解析(5)
开发语言·c++·算法
lly20240624 分钟前
《堆的 shift down》
开发语言
cpp_250129 分钟前
P10570 [JRKSJ R8] 网球
数据结构·c++·算法·题解
cpp_250136 分钟前
P8377 [PFOI Round1] 暴龙的火锅
数据结构·c++·算法·题解·洛谷
黎雁·泠崖43 分钟前
【魔法森林冒险】2/14 抽象层设计:Figure/Person类(所有角色的基石)
java·开发语言
程序员老舅1 小时前
C++高并发精髓:无锁队列深度解析
linux·c++·内存管理·c/c++·原子操作·无锁队列
划破黑暗的第一缕曙光1 小时前
[C++]:2.类和对象(上)
c++·类和对象
季明洵1 小时前
C语言实现单链表
c语言·开发语言·数据结构·算法·链表
墨雪不会编程1 小时前
C++之【深入理解Vector】三部曲最终章
开发语言·c++