C++多态(全)

news/2024/9/23 4:38:19/

多态

概念

调用函数的多种形态,

多态构成条件

1)父子类完成虚函数的重写(三同:函数名,参数,返回值相同)

2)父类的指针或者引用调用虚函数

虚函数

被virtual修饰的类成员函数

注意

1)只有类的非静态成员函数前才可以加上virtual 

2)虚函数的virtual与虚继承的virtual是同一个关键字。虚函数中的virtual是为了实现多态,虚继承的virtual是为了菱形继承中数据冗余和二义性。

虚函数的重写

也叫虚函数的覆盖

派生类中有一个完全相同的虚函数(返回值类型相同,函数名相同,参数列表相同),就叫做派生类的虚函数重写了基类的虚函数

结果:通过父类Person的指针或引用调用虚函数

父类指针要是指向父类对象则调用父类的虚函数

要是指向子类对象则调用子类虚函数

#include<iostream>
using namespace std;
class Person
{
public:virtual void BuyTicket(){cout << "买票半价" << endl;}
};
class Student :public Person
{
public:virtual void BuyTicket(){cout << "买票半价" << endl;}
};
void Func(Person& people)
{people.BuyTicket();
}
int main()
{Student s;Func(s);return 0;
}
注意

1)派生类的虚函数可以不用加上virtual关键字(不规范,建议加上)

虚函数的两个例外

1)协变

基类和派生类的返回值不同

当基类虚函数返回基类对象的指针或引用

派生类虚函数返回派生类对象的指针或引用

#include<iostream>
using namespace std;//基类
class A
{};
//子类
class B : public A
{};
//基类
class Person
{
public://返回基类A的指针virtual A* fun(){cout << "A* Person::f()" << endl;return new A;}
};
//子类
class Student : public Person
{
public://返回子类B的指针virtual B* fun(){cout << "B* Student::f()" << endl;return new B;}
};
void Func(Person& p)
{p.fun();
}
int main()
{Student s;Func(s);return 0;
}

2)析构函数的重写

基类和派生类的析构函数名字不同

当基类的析构函数是虚函数,只要派生类析构函数定义,就构成重写

作用:

要是没有重写,指向子类的指针只会调用父类的析构函数,有可能造成内存泄漏

推荐:

一般把父类的析构函数写成虚函数,反之发生内存泄漏

注意:

在继承中,子类和父类的析构函数会构成隐藏就是因为,虽然子类析构函数和父类的析构函数函数名虽然不同,但是为了构成重写,编译后的析构函数名字会统一处理为destructor();

void test2()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2;//本来希望指向父类的指针析构父类//指向子类的指针去析构子类//因此需要虚函数,构成重写
}

c++11

1)override:检查派生类虚函数是否重写了基类的某个虚函数,没有则编译错误

//子类
class Student : public Person
{
public://子类完成了父类虚函数的重写,编译通过virtual void BuyTicket() override{cout << "买票-半价" << endl;}
};

2)final:修饰虚函数,表示该虚函数不能再重写

//父类
class Person
{
public://被final修饰,该虚函数不能再被重写virtual void BuyTicket() final{cout << "买票-全价" << endl;}
};

易错例题

纯虚函数

在虚函数后面写上=0

抽象类(接口类):包含纯虚函数的类

特点

1)抽象类不能实例化对象

2)强制派生类重写虚函数(不重写则会继承纯虚函数,又变为抽象类了又不能实例化对象了)

3)用抽象类(父类)的指针调用虚函数

作用

1)抽象类能更好的

#include <iostream>
using namespace std;
//抽象类(接口类)
class Car
{
public://纯虚函数virtual void Drive() = 0;
};
int main()
{Car c; //抽象类不能实例化出对象,errorreturn 0;
}

#include <iostream>
using namespace std;
//抽象类(接口类)
class Car
{
public://纯虚函数virtual void Drive() = 0;
};
//派生类
class Benz : public Car
{
public://重写纯虚函数virtual void Drive(){cout << "Benz-舒适" << endl;}
};
//派生类
class BMV : public Car
{
public://重写纯虚函数virtual void Drive(){cout << "BMV-操控" << endl;}
};
int main()
{//派生类重写了纯虚函数,可以实例化出对象Benz b1;BMV b2;//不同对象用基类指针调用Drive函数,完成不同的行为Car* p1 = &b1;Car* p2 = &b2;p1->Drive();  //Benz-舒适p2->Drive();  //BMV-操控return 0;
}

抽象类作用

1)用来表达没有实例对象的抽象类型

2)强制子类重写虚函数(同override)

原理

多态调用:运行时,到指向对象的虚表中找虚函数调用

普通调用:编译时,调用的对象是那个类型就调用它的函数

虚表:虚函数表,存虚函数的地址,目标实现多态

虚基表:存的是当前位置距离虚基类部分的偏移量,解决菱形继承和二义性的问题

虚函数和普通函数一样:在代码段中,不是在虚表中的(虚表内的是虚函数的地址

虚表在常量区


http://www.ppmy.cn/news/1446115.html

相关文章

机器人模型匹配控制(MPC)MATLAB实现

模型匹配控制&#xff08;Model matching control&#xff09;是指设计一个控制器使闭环系统的传递函数tf(s)与td(s)相一致&#xff01; mpcDesigner 可以分为&#xff1a; 2时域精确模型匹配控制3频域精确模型匹配控制 机械臂控制中应用模型匹配控制&#xff08;Model Matc…

本地生活服务商是什么?选哪个平台比较好?

随着各大平台本地生活服务板块的陆续上线&#xff0c;本地生活服务商这一新兴职业也应运而生&#xff0c;并且人数不断增多。但是&#xff0c;仍有许多人不清楚本地生活服务商是什么&#xff0c;对成为本地生活服务商的相关申请流程也不甚了解。那么本期&#xff0c;我们就用通…

鸿蒙南向开发环境的搭建(OpenHarmony)

在嵌入式开发中&#xff0c;很多开发者习惯于使用Windows进行代码的编辑&#xff0c;比如使用Windows的Visual StudioCode进行OpenHarmony代码的开发。但当前阶段&#xff0c;大部分的开发板源码还不支持在Windows环境下进行编译&#xff0c;如Hi3861、Hi3516系列开发板。因此&…

自动控制原理学习--平衡小车的控制算法(一)

基于单片机STM32的两轮平衡小车&#xff0c;单片机的各种IO、定时器、通讯等等一大堆要理解、编程&#xff0c;但这些都是琐碎的文档知识&#xff0c;需要花时间看各个模块的接口文档进而编程&#xff0c;需要良好的编程逻辑思维&#xff0c;去获取相关的传感模块信息&#xff…

ETL简介以及使用ETL(Kettle)进行数据接入的具体例子

目录 ETL介绍 ETL简介 ETL包含的三部分 ETL基本概念 ETL资源库 ETL变量 业务表梳理以及接入规划 数据接入流程 业务表梳理 ETL任务规范 接入规划 数据接入中的方便工具 具体例子 导出生产表信息 1、ORACLE 2、MYSQL ETL数据增量抽取任务开发 1、ORACLE通用流程…

智慧农场系统 搭建重点,会用到哪些三方服务?

智慧农场小游戏的搭建重点主要集中在游戏设计、用户体验、数据安全和稳定性等方面。为了实现这些目标&#xff0c;可能会用到以下第三方服务&#xff1a; 游戏引擎和开发工具&#xff1a;使用成熟的游戏引擎和开发工具可以极大地简化开发流程&#xff0c;提高开发效率。例如&a…

【ARMv9 DSU-120 系列 4 -- Utility bus 详细介绍 1】

请阅读【Arm DynamIQ™ Shared Unit-120 专栏 】 文章目录 DSU-120 Utility bus事务类型访问大小事务长度安全状态总结缓存控制(ARCACHEU 或 AWCACHEU)突发类型(ARBURSTU 或 AWBURSTU)锁定信号(ARLOCKU 或 AWLOCKU)Utility bus acceptance capabilities

重磅!!!监控分布式NVIDIA-GPU状态

简介&#xff1a;Uptime Kuma是一个易于使用的自托管监控工具&#xff0c;它的界面干净简洁&#xff0c;部署和使用都非常方便&#xff0c;用来监控GPU是否在占用&#xff0c;非常美观。 历史攻略&#xff1a; docker应用&#xff1a;搭建uptime-kuma监控站点 win下持续观察…