C++多态

news/2024/4/29 13:10:25

多态

多态是C++面向对象三大特性之一。
多态分为两类:

  • 静态多态:函数重载和运算符重载属于静态多态,复用函数名
  • 动态多态:派生类和虚函数实现运行时多态

静态多态和动态多态区别:

  • 静态多态的函数地址早绑定——编译阶段确定函数地址
  • 动态多态的函数地址晚绑定——运行阶段确定函数地址
#include<iostream>
using namespace std;class Animal {
public://虚函数virtual void speak() {cout << "动物在说话" << endl;}
};class Cat : public Animal {
public:void speak() {cout << "小猫在喵喵" << endl;}
};class Dog : public Animal {
public:void speak() {cout << "小狗在汪汪" << endl;}
};//地址早绑定,在编译阶段确定函数地址
void doSpeak(Animal& animal) {animal.speak();
}int main() {Cat cat;doSpeak(cat);Dog dog;doSpeak(dog);return 0;
}

动态多态满足条件:

  1. 有继承关系
  2. 子类重写父类的虚函数

重写:函数返回值类型 函数名称 参数列表 完全相同

动态多态使用:
父类的指针或引用,指向子类的对象。

当子类重写父类的虚函数时
子类中的虚函数表内部会替换成子类的虚函数地址

多态优点

  • 代码组织结构清晰
  • 可读性强
  • 利于前期和后期的扩展以及维护

开闭原则:对扩展进行开放,对修改进行关闭。

纯虚函数和抽象类

在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容。

因此可以将虚函数改为纯虚函数。

纯虚函数语法:

virtual 返回值类型 函数名(参数列表) = 0;

当类中有了纯虚函数,这个类也称为抽象类。
抽象类无法实例化对象
子类必须重写抽象类中的纯虚函数,否则也属于抽象类。

由于传入的对象不同,一个接口有多种形态

虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码。

纯虚析构需要声明也需要实现
有了纯虚析构之后,这个类也属于抽象类,无法实例化对象

#include<iostream>
using namespace std;class Animal {
public:virtual void speak() = 0;Animal() {cout << "Animal构造函数调用" << endl;}//利用虚析构可以解决,父类指针释放子类对象时不干净的问题/*virtual ~Animal() {cout << "Animal虚析构函数调用" << endl;}*/virtual ~Animal() = 0;
};Animal::~Animal() {cout << "Animal纯虚析构函数调用" << endl;
}class Cat : public Animal {
public:Cat(string name) {cout << "Cat构造函数调用" << endl;m_Name = new string(name);}virtual void speak() {cout << *m_Name << "小猫喵喵" << endl;}~Cat() {if (m_Name != NULL) {delete m_Name;m_Name = NULL;cout << "Cat析构函数调用" << endl;}}string *m_Name;
};int main() {Animal* animal = new Cat("Tom");animal->speak();//父类指针在析构时候,不会调用子类中析构函数,导致子类如果有堆区属性,会产生内存泄漏delete animal;return 0;
}

虚析构或纯虚析构都是用来解决通过父类指针释放子类对象的问题。
如果子类没有堆区数据,可以不写虚析构或纯虚析构。
拥有纯虚析构函数的类也属于抽象类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.cpky.cn/p/10549.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

haproxy-高性能负载均衡反向代理服务

目录 一、HAProxy&#xff08;High Availability Proxy&#xff09;概述 1、HAProxy的概念 2、HAProxy的主要特性 3、HAProxy的优缺点 4、Haproxy负载均衡策略 5、LVS、nginx、HAProxy的区别 二、安装HAProxy 1、yum安装 2、第三方rpm包安装 3、编译安装 3.1 解决 l…

java数据结构与算法刷题-----LeetCode47. 全排列 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 暴力回溯2. 分区法回溯 此题为46题的衍生题&#xff0c;在46题…

Vue的渲染原理

列表渲染 列表渲染 v-for指令写在循环项上&#xff1a;v-for“(一个参数或者两个参数) in/of 要遍历的数组、对象、字符串、指定次数” 遍历数组时参数分别是数组中元素(可以是一个对象)和元素所在下标(从0开始)遍历对象时参数分别是属性值和属性名遍历字符串时参数分别是单…

排序算法(Python)

选择排序 def selection_sort(a):nlen(a)for i in range(n-1):minifor j in range(i1,n):if a[j]<a[min]:minja[i],a[min]a[min],a[i] a[125,142,23,654,454,1,456] selection_sort(a) print(a) 简而概之&#xff0c;逐个比较&#xff0c;交换顺序 结合字典序进行排序 im…

运用html相关知识编写导航栏和二级菜单

相关代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><s…

Gitlab光速发起Merge Request

前言 在我们日常开发过程中需要经常使用到Merge Request&#xff0c;在使用过程中我们需要来回在开发工具和UI界面之前来回切换&#xff0c;十分麻烦。那有没有一种办法可以时间直接开发开工具中直接发起Merge Request呢&#xff1f; 答案是有的。 使用 Git 命令方式创建 Me…