C++ DAY06 c++多态

news/2024/10/23 7:31:57/

简介

一个事物的多种形态 , 简称多态
物的多态
同一个人在不同人面前展现是不同的
:
        在我面前
        在对象面前
        在朋友面前
        在父母面前
事的多态
吃饭
        中国人 筷子 熟食
        美国人 刀叉 7 分熟
        日本人 筷子 生食
        印度人 手
睡觉
        中国人 床上
        日本人 榻榻米
        侧卧
        平躺
        趴着

上行与下行

上行

子类转父类
语法
        父类名 * 父类对象指针 = 子类对象指针 ;
        父类名& 父类对象名 = 子类对象 ;
注意 :
        无风险, 无需强转

下行

父类转换为子类
语法
        子类名 * 子类对象指针 = ( 子类名 *) 父类对象指针 ;
        子类名& 子类对象 = ( 子类名 &) 父类对象 ;
注意 :
        有风险, 需强转

重写

重载

        同一作用域下, 函数名形同相同 ,形参列表不同        

重定义

        函数继承时,继承关系中,函数名相同即可

重写

        继承关系中,返回值类型相同,函数名形同,形参列表相同,函数体不同

c++多态分类

静态多态 ( 早绑定 , 静态联编 )
        概念:在编译阶段 就确定函数的入口地址.
        又名: 静态联编 , 早绑定
        如: 函数重载 , 运算符重载 , 重定义等
动态多态 ( 晚绑定 , 动态联编 )
        概念: 在运行阶段确定程序入口地址
        又名: 动态联编 , 晚绑定
        如: 虚函数 , 重写

引入

要求 : 设计一个函数 , 根据传入的对象调用重写的方式
代码
#include <iostream>
using namespace std;
class Anim{
public:void test01(){cout << "动物test01" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}
};
class Cat:public Anim{
public:void test01(){cout << "猫类test01" << endl;}
};
void method01(Anim& a)
{
a.test01();
}
int main(int argc, char *argv[])
{Dog d;Cat c;method01(d);method01(c);return 0;
}
运行结果
原因
        父类指针只能操作子类空间中的父类部分。

虚函数

概念

        virtual修饰的成员函数 , 就是虚函数

语法    

virtual 返回值类型 函数名 ( 形参列表 )
{
        方法体
}

特点

当子类转换为父类后
使用该父类调用使用 virtual 修饰的函数 , 调用的是子类重写后的
使用该父类调用普通函数 , 调用的是父类的该函数

补充概念

重写 : 在继承关系中 , 子类方法与父类方法 , 返回值类型一致 , 函数名相同 , 形参列表相同
注意 : 子类重写父类虚函数 , 子类该函数默认为虚函数

代码

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01(){cout << "动物test01" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}
};
class Cat:public Anim{
public:void test01(){cout << "猫类test01" << endl;}
};
void method01(Anim& a)
{a.test01();
}
int main(int argc, char *argv[])
{Dog d;Cat c;method01(d);method01(c);return 0;
}

动态绑定条件(重要)

有继承,子类重写父类的虚函数,父类指针或引用指向子类空间。父类指针或引用才能调用子类重写的虚函数。
错误演示
        B b;
        //此时会调用父类的拷贝构造 , 会产生一个新的父类对象 , 该父类对象 a 与子类对象b是两个独立空间 ,所以此时使用a 对象调用 test01 依据会执行父类的 test01 函数
        //A a = b;
        A& a = b;
        a.test01();

动态绑定原理(重要)

父类有虚函数,产生虚函数指针指向虚函数表,表中纪录的是父类的虚函数地址。
如果子类继承父类,那么子类会继承父类的虚函数指针以及虚函数表。
如果子类重写父类的虚函数,会将将虚函数表纪录的入口地址修改成子类重写的函数入口地址。
这时父类指针指向子类空间,父类指针调用虚函数就间接调用子类重写的虚函数。

纯虚函数

概念

        父类的虚函数没有函数体

语法

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

示例

#include <iostream>
using namespace std;
class Anim{
public:
//纯虚函数virtual void test01() = 0;
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}
};
class Cat:public Anim{
public:void test01(){cout << "猫类test01" << endl;}
};
void method01(Anim& a)
{a.test01();
}
int main(int argc, char *argv[])
{Dog d;Cat c;method01(d);method01(c);return 0;
}

注意

纯虚函数所在的类不能直接创建对象 , 这种类被称为抽象类
子类继承与抽象类 , 要么重写父类提供的所有纯虚函数 , 要么自己也是抽象类

虚析函数

引入

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01() = 0;Anim(){cout << "父类构造" << endl;}~Anim(){cout << "父类析构" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}Dog(){cout << "子类Dog构造" << endl;}~Dog(){cout << "子类Dog析构" << endl;}
};
int main(int argc, char *argv[])
{Dog *d = new Dog();Anim *a = d;delete a;return 0;
}

结果

        问题: 没有子类析构函数调用
        解决方案: 将父类的析构函数 设置成 虚析构

语法

virtual ~ 析构函数 ()
{
}

代码

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01() = 0;Anim(){cout << "父类构造" << endl;}virtual ~Anim(){cout << "父类析构" << endl;}
};
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}Dog(){cout << "子类Dog构造" << endl;}~Dog(){cout << "子类Dog析构" << endl;}
};
int main(int argc, char *argv[])
{Dog *d = new Dog();Anim *a = d;delete a;return 0;
}

结果:

纯虚析构(了解)

语法

        virtual 析构函数名 () = 0;

注意

        需要在类外实现析构函数

#include <iostream>
using namespace std;
class Anim{
public:virtual void test01() = 0;Anim(){cout << "父类构造" << endl;}virtual ~Anim() = 0;
};
Anim::~Anim()
{cout << "父类析构" << endl;
}
class Dog:public Anim{
public:void test01(){cout << "狗类test01" << endl;}Dog(){cout << "子类Dog构造" << endl;}~Dog(){cout << "子类Dog析构" << endl;}
};
int main(int argc, char *argv[])
{Dog *d = new Dog();Anim *a = d;delete a;return 0;
}

结果

总结

1、虚函数和纯虚函数的区别?
        虚函数和纯虚函数都是为了通过父类指针调用子类重写的虚函数。
        虚函数 不=0 修饰 , 有函数体 , 所在的类不是抽象类 , 可以实例化对象。
        纯虚函数 =0 修饰 , 没有函数体 , 所在的类是抽象类 , 不可以实例化对象。
2、虚析构和纯虚析构的区别
        虚析构和纯虚析构都是为了通过父类指针释放子类的所有空间( 父类部分 , 子类部分 )
        虚析构不=0 修饰 , 所在的类不是抽象类 , 可以实例化对象。
        纯虚析构=0 修饰 , 类外实现函数体 , 所在的类是抽象类 , 不可以实例化对象。
3、重载、重定义、重写的区别
        重载:没有继承,函数重载和运算符重载。函数名相同,参数的个数,顺序、类型可以不同,返回值类型不能作为重载条件。
        重定义:有继承,子类重定义父类同名函数(非虚函数)。返回值类型,形参可以相同 和 不同。
        重写:有继承,子类重写父类的虚函数。函数名,返回值类型,形参必须和父类同名函数一致。

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

相关文章

API接口接入1688电商数据平台获取商品详情数据示例

1688电商数据平台是一个提供海量商品信息的数据平台&#xff0c;通过API接口可以方便地获取商品详情数据。以下是一个示例&#xff0c;演示如何接入1688电商数据平台&#xff0c;获取商品详情数据。 步骤一&#xff1a;注册1688账号并获取API权限 首先需要在1688电商数据平台…

测试集为什么不能当做验证集使用?

测试集和验证集在机器学习中有不同的目的和用途&#xff0c;因此通常不应该混用。主要的原因包括&#xff1a; 测试集的独立性&#xff1a; 测试集的主要目的是评估模型在未见过的数据上的泛化性能&#xff0c;模型在测试集上的表现应该反映其在实际应用中的性能。如果测试集被…

java中的抽象

1.当一个类中给出的信息不够全面时&#xff0c;&#xff08;比方说有无法确定的行为&#xff09;&#xff0c;它给出的信息不足以描绘出一个具体的对象&#xff0c;这时我们往往不会实例化该类&#xff0c;这种类就是抽象类。 2. 在Java中&#xff0c;我们通过在类前添加关键字…

SpringBoot2—运维实用篇

目录 打包与运行 • 程序打包与运行&#xff08;Windows版&#xff09; • 程序运行&#xff08;Linux版&#xff09; 配置高级 • 临时属性设置 • 配置文件分类 • 自定义配置文件 多环境开发 多环境开发&#xff08;yaml单一文件版&#xff09; 多环境开发&am…

电子秤方案:做一个宠物勺方案设计

养宠物是一件费心劳力的事情&#xff0c;但同时也是能够给你带来快乐和幸福感的事情。就是有时候会怕宠物毫无征兆地生病令人措手不及&#xff0c;所以电子秤方案设计鼎盛合科技分享一个小方案&#xff0c;能够及时了解到宠物的身体状况问题。 蓝牙宠物勺是一种具有记录和称重…

SpringBoot 请求参数和响应参数转换为下划线

文章目录 前言请求参数将下划线转换为驼峰响应参数将驼峰转换为下划线方式一 使用Jackson方式处理方式二 在配置文件中修改jackson.default-property-inclusion 说明jackson.property-naming-strategy 说明前言 在开发SpringBoot项目时,我们经常需要处理参数的命名规范。有时…

【报错记录】解决使用Kotlin写的SpringBoot项目使用Aspect切面无法生效的问题

前言 为了能在SpringBoot使用Kotlin&#xff0c;真的是各种坑都彩礼一遍&#xff0c;这次遇到的问题是Aspect无法对Kotlin代码生效。我这里的使用场景是使用切面切Controller中的方法&#xff0c;用来对接口进行一些初始化和收尾工作。 Aspect在Controller类还是Java代码的时…

Leo赠书活动-09期 【如何拿下数学】文末送书

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…