当前位置: 首页 > article >正文

学习记录——day42 多态

静态多态:函数重载、运算符重载

学习记录——day41 运算符重载-CSDN博客

学习记录——day39 C++对函数的扩充 函数重载 函数的默认参数 哑元-CSDN博客

动态多态:函数重写

一、多态的实现

        父类的指针或引用可以指向子类的对象,进而调用子类中重写的父类的虚函数

二、函数重写 override

1、函数重写是发生在父子类中

2、要求在子类中重写与父类函数中函数原型相同的函数

        原型相同:返回值类型、函数名、参数列表都相同

三、虚函数

1)定义格式:在定义函数前加关键字 virtual,此时的函数就是虚函数

2)需要在父类中定义虚函数,子类中可以进行重写也可以不重写

3)当一个类中,如果定义了虚函数,那么该类会增加一个指针的大小,这个指针指向虚函数表

4)如果一个类中的某个函数定义成虚函数,那么该类的子子孙孙类中的该函数都是虚函数,即使没有加virtual

四、overload(函数重载)、override(函数重写)、hide(隐藏)的相关概念

1、函数重载:函数名相同,形参列表必须不同

        1)作用域相同

        2)函数名相同

        3)参数列表必须不同(个数、类型)

        4)有无 virtual 都无所谓

        5)跟返回值没有关系

2、函数重写:子类中重写父类的虚函数

        1)作用域发生在父子类中

        2)函数原型相同(返回值、参数个数、参数类型、函数名)

        3)父类中的函数必须要有 virtual 关键字

3、函数隐藏:子类中定义与父类同名的函数

        1)作用域发生在父子俩中

        2)函数名相同

        3)返回值可以不同

        4)参数相同

        5)没有virtual修饰

五、纯虚函数

1、对于有些类而言,类中的相关成员函数没有实现的意义,主要是让子类来完成重写操作的

2、以便于使用父类的指针或引用指向子类对象,调用子类中重写的父类的虚函数

3、我们就可以将这样的函数设置成纯虚函数

4、定义格式: virtual 返回值类型 函数名(形参列表) = 0;

5、要求子类中必须对这些纯虚函数进行重写

6、抽象类:包含纯虚函数的类叫做抽象类,抽象类是不能实例化对象的

7、如果包含纯虚函数的子类中没有重写其虚函数,那么其子类也是抽象类,子类中的该函数也还是纯虚函数

六、虚析构函数

1、当使用父类指针指向子类对象时,构造时会正常先构造父类后构造子类,但是在使用delete释放内存空间时,由于父类指针的作用域,只作用在子类的父类空间内,所以,只会调用父类的析构函数,子类自己的空间就泄露了

2、此时可以使用虚析构函数来解决:定义析构函数时,在函数头前面加关键字virtual即可

3、虚析构函数能正确引导delete关键字,在释放父类空间时,把子类的空间一并释放

4、如果父类的析构函数为虚析构函数,那么该类的子子孙孙类中的析构函数都是虚析构函数

七、示例

#include <iostream>

using namespace std;

class Shape
{
public:
    Shape(){}
    virtual ~Shape(){}//虚析构函数

    //定义虚函数
    virtual void show()
    {
        cout<<"Shape virtual show"<<endl;
    }

};

class Circle:public Shape
{
private:
    int radius;
public:
    Circle(){}
    Circle(int r):radius(r){}
    ~Circle(){}
    void show() override//函数重写
    {
        cout<<"面积为:"<<radius*radius*3.14<<endl;
        cout<<"周长为"<<2*3.14*radius<<endl;
    }
};

class Rectangle:public Shape
{
private:
    int h;
    int w;
public:
    Rectangle(){}
    Rectangle(int h,int w):h(h),w(w){}
    ~Rectangle(){}
    void show() override
    {
        cout<<"面积为:"<<h*w<<endl;
        cout<<"周长为"<<(h+w)*2<<endl;
    }
};

//定义全局函数调用
void fun(Shape& s)
{
    s.show();
}

int main()
{
    Circle c(5);
    fun(c);

    Rectangle r(3,5);
    fun(r);

    cout<<"************"<<endl;

    Shape *ptr = &c;
    ptr->show();//重写的虚函数
    ptr->Shape::show();//原虚函数

    return 0;
}


http://www.kler.cn/a/289377.html

相关文章:

  • 040 线程池
  • JavaScript高级程序设计基础(四)
  • 【MySQL】数据库表连接简明解释
  • 【STM32】基于SPI协议读写SD,详解!
  • 【Qt】Macbook M1下载安装
  • 程序员年薪百万秘籍(一)
  • 算法图解(2)
  • 【Day08】
  • weak_ptr是否有计数方式,在哪分配的空间。
  • MacBook Pro M3 安装 Node.js v14 的兼容性
  • 进阶SpringBoot之 Shiro(6)整合 Thymeleaf
  • 【word导出带图片】使用docxtemplater导出word,通知书形式的word
  • 0基础学习爬虫系列:Python环境搭建
  • Anaconda的环境管理操作命令详解-学习篇
  • mysql创建数据库和表
  • list的简单实现
  • springblade-JWT认证缺陷漏洞CVE-2021-44910
  • 4.1 数据分析-excel 基本操作
  • Java语言程序设计基础篇_编程练习题**17.21 (十六进制编辑器)
  • LinkedList与链表
  • Java基于微信小程序的实习管理系统
  • C++ 设计模式——中介者模式
  • Django 安装指南
  • notepad++软件介绍(含安装包)
  • 力扣56-合并区间(Java详细题解)
  • Electron 项目实战 02:打包和自动更新