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

C++_20_多态

多继承会造成 菱形继承** 使用虚继承来解决

不是给爷爷类加 也不是给子类加 是给父类加 虚基指针和虚基表

多态

概念:

概念: 一个事物的多种形态,简称多态

如:

  • 对象的多态

    ​ 张三

    ​ 在对象面前 怂

    ​ 在朋友面前 谄媚

    ​ 在父母面前 孝顺

  • 事的多态

    ​ 吃饭

    ​ 中国人用筷子

    ​ 美国人用刀叉

    ​ 印度人用手抓

  • 事务的多态

    • 上行: 子类对象换为父类对象
    • 下行 : 父类对象换为子类对象
  • 事的多态

    • 重载:
    • 重写:
    • 重定义:

物的多态:

上行:

特点: 自动转换 无风险

概念:子类对象转换为父类对象

语法:

子类对象 转换为 父类对象

  • 父类名 &父类对象名 = 子类对象;

子类对象指针 转换为 父类对象指针

  • 父类名 *父类对象指针 = 子类对象指针;

示例:

在这里插入图片描述

注意:

子类对象转换为父类对象或父类对象指针后,使用转换后父类对象或父类对象指针 无法使用子类特有的成员

包括 成员对象 和 成员函数

下行:

概念: 父类对象 转换 为 子类对象 父类对象指针 转换为 子类对象指针

特点: 有风险 需要强制转换 语法就带

语法:

子类名 &子类对象 = ( 子类名& )父类对象名;

  • Cat cat = (Cat &) anim; // Cat &强制转换

子类名 子类对象指针 = ( 子类名 * ) 父类对象指针名;

事的多态

重载

  • 同一个类中函数名相同,形参列表不同,称为重载

重写

  • 继承关系中,子类成员函数与父类成员函数函数名相同,形参列表相同,返回值类型相同

重定义

  • 函数名相同,即为重定义 c不允许重定义 C++允许

虚函数:

概念: 使用 virtual 修饰的函数

语法:

 virtual 返回值类型 函数名(){函数体;}

原理: 使用 虚基指针和虚基表

特定:

  • 当子类重写 父类 提供的 虚 函数

  • 当子类对象转换为父类对象 ,使用转换的父类对象调用 重写的虚函数,此时执行的子类重写后的

未使用 虚函数 重写父类的函数后 造成想要的效果出现不了

在这里插入图片描述

  • 发现打印的是A 不是想要的B

  • 解决方式
    

    虚函数: virtual 父类函数 加 virtual

#include <iostream>
using namespace std;
// 虚函数 解决 继承重写的问题
class A
{
public:virtual void method(){cout << " 父类 A" << endl;}
};class B : public A
{
public:void method(){cout << " 子类 B" << endl;}
};
int main(int argc, char const *argv[])
{B b;A &a = b;   // 上行  将 b对象 转为 A 类对象a.method();return 0;
}//  有问题 没出预期效果 没出 B   应该出 B

在这里插入图片描述

  • 虚函数 是有函数体的 不知道才写纯虚 函数 知道就写虚函数 要是不知道函数体就写
    纯 虚函数 并子类重写 父类的所有纯虚函数 不然创建不了对象

纯虚函数:

  • 没有函数体
  • 如果一个类中有虚函数,该类无法直接创建对象,这种类称为抽象类
  • 子类继承于抽象类,要么重写所有纯虚函数,要么

概念:

  • 没有函数体的虚函数
  • 如果一个类中有纯虚函数,该类无法直接创建对象,这种类称为抽象类子类继承与抽象类,要么重写抽象类中所有的纯虚函数要么自己也是抽象类

语法:

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

使用完 释放内存的时候 担心 内存释放的不干净

父类 anim 子类dog 释放dog 出现问题 出现 只释放了 anim 内存 而没释放 dog

释放 anim 就两者都释放掉了 但就是担心你释放的时候写错 忘记释放内存 使用虚析构造解决

在这里插入图片描述

在这里插入图片描述

#include <iostream>
using namespace std;// 纯虚函数class A{
public:
virtual void me01() = 0 ; // 纯虚函数 1virtual void me02() = 0 ; // 纯虚函数 2 只有重写父类的纯虚函数之后才能创建对象};class B :public A{public://重写父类所有纯虚函数  重写的不是全部的时候 就创建不了对象void me01(){cout<<"B 01"<<endl;}void me02(){cout<<"B 02"<<endl;}};int main(int argc, char const *argv[])
{B b;  //创建对象才正常   return 0;}

虚析构造:【*】

概念:

  • 使用 virtual 修饰的析构函数

特点:

  • 子类对象指针转换为父类对象指针,此时delete父类对象指针,只会调用父类析构函数
  • 如果父类析构函数为虚析构造,那么也将调用子类析构函数

语法: 【注意 是给父类中写 】

virtual ~父类名()
{}

示例:

在这里插入图片描述

在这里插入图片描述

纯虚析构:【**】

优化虚析函数版的

因为要分文件 所以优化用这个

概念 : 没有函数体的虚析构造

语法 :

virtual ~父类名()= 0;

注意 :

  • 类外实现
  • 纯虚析构也是纯虚函数
  • 顾纯虚析构的类也是抽象类,此时无法创建对象

案例:

小张是个宠物医生

张女士 养了一只狗叫旺财

李女士 养了一只猫叫布丁

分析:

存在的对象

​ 小张 张女士 李女士 旺财 布丁

类:

​ 动物:人类 医生类 ​ 狗类 猫类

​ A 动物类:

​ 成员变量: name

​ 成员函数: 1 speak 2 无参构造 3 有参构造 4 拷贝构造 5 纯虚析构

​ B 人类:

​ 特有成员: 宠物 [anim]

​ 重写父类speak函数

​ 无参构造 有参构造 拷贝构造 纯虚析构

​ C 医生类:

​ 特有函数: work:治病

​ 无参构造

​ 有参构造

​ 拷贝构造

​ 纯虚析构

​ D 狗类

​ 重写父类speak函数

​ 无参构造

​ 有参构造

​ 拷贝构造

​ 纯虚析构

​E 猫类

​ 重写父类speak函数

​ 无参构造

​ 有参构造

​ 拷贝构造

​ 纯虚析构

​==============
创建对象

​ 建立关系

分文件编写:

头文件:

anim.h
#ifndef xx
#define xx
#include <iostream>
#include <stdlib.h>
#include <string.h>
class Anim
{
private:char *name;public:Anim();Anim(char *name);Anim(const Anim &anim);virtual ~Anim();                    // 纯虚析构  virtual ~父类名()= 0;virtual void speak(char *info) = 0; // 纯虚函数 virtua]返回值类型函数名(形参列表)= 0;char *getName() const;void setName(char *name);
};
#endif
person.h
#ifndef tt
#define tt
#include <iostream>
#include "anim.h"
using namespace std;
class Person : public Anim
{private:Anim* anim;public:Person();Person(char *name);Person(char *name,Anim* anim);Person(const Person &p);~Person() ; // 纯虚函数 virtua]返回值类型函数名(形参列表)= 0;Anim* getAnim() const;void setAnim(Anim*  anim);void speak(char *info);
};
#endif
doctor.h
#ifndef do
#define do
#include <iostream>
#include "person.h"
class Doctor : public Person
{
public:Doctor();Doctor(char *name);// virtual ~Doctor() = 0;~Doctor();void work(Anim *anim);
};
#endif
dog.cpp
#ifndef dogg
#define dogg
#include <iostream>
#include "anim.h"
class Dog : public Anim
{
public:Dog();Dog(char *name);// virtual ~Dog() = 0;  使用这个有问题~Dog();void speak(char *info);
};
#endif
cat.h
#ifndef catt
#define catt
#include <iostream>
#include "anim.h"
class Cat : public Anim
{
public:Cat();Cat(char *name);~Cat();void speak(char *info);
};
#endif

源文件

anim.cpp
#include "anim.h"
Anim::Anim() : name(NULL) {};
Anim::Anim(char *name)
{int len = strlen(name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name,name);
}
Anim::Anim(const Anim &anim)
{int len = strlen(anim.name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name,anim.name);
}
Anim::~Anim()
{if (name != NULL){free(name);name = NULL;}
}
char * Anim::getName() const
{return name;
}void Anim::setName(char *name)
{if (this->name != NULL){free (this->name);}int len = strlen(name);this->name = (char *)calloc(len + 1, 1);strcpy(this->name,name);
}
person.cpp
#include "person.h"
Person::Person() : anim(NULL) {}
Person::Person(char *name) : Anim(name), anim(NULL) {}
Person::Person(char *name, Anim *anim) : Anim(name), anim(anim) {}
Person::Person(const Person &person)
{// 因为形参 person 使用了const 修饰 意味着不能修改其成员// 此时使用person调用 其函数 系统担心 函数内部对其成员进行修改,// 顾调用 的函数必须是使用const 修饰的成员函数this->anim = person.getAnim(); char *name = person.getName();  //加const
}
Person::~Person() {} // 纯虚析构
Anim *Person::getAnim() const
{return anim;
}
void Person::setAnim(Anim *anim)
{this->anim = anim;
}
void Person::speak(char *info)
{cout << this->getName() << " "<<endl;
}
doctor.cpp
#include "doctor.h"
Doctor::Doctor() {}
Doctor::Doctor(char *name) : Person(name) {}
Doctor::~Doctor() {}
// 给宠物看病  将宠物传进来
void Doctor::work(Anim *anim)
{cout << this->getName() << "给" << anim->getName() << "看看病!" << endl;anim->speak(NULL);
}
cat.cpp
#ifndef catt
#define catt
#include <iostream>
#include "anim.h"
class Cat : public Anim
{
public:Cat();Cat(char *name);~Cat();void speak(char *info);
};
#endif
dog.cpp
#include "dog.h"
using namespace std;
Dog::Dog() {};
Dog::Dog(char *name) : Anim(name) {}
Dog::~Dog() {}
void Dog::speak(char *info)
{cout << getName() << ":" << "汪汪汪" << endl;
}

执行文件:

main.cpp
#include <iostream>
#include "anim.h"
#include "doctor.h"
#include "cat.h"
#include "dog.h"
#include "person.h"
using namespace std;
int main(int argc, char const *argv[])
{Doctor *d = new Doctor("小张");Dog *dog  = new Dog("旺财");Cat *cat =new Cat("大橘");Person* p1 = new Person("张女士",dog);Person* p2 = new Person("李女士",cat);d->work(p1->getAnim());d->work(p2->getAnim());return 0;
}

在这里插入图片描述


http://www.mrgr.cn/news/27772.html

相关文章:

  • Grass脚本2倍速多账号
  • linux下编译安装memcached
  • 【测试框架篇】单元测试框架pytest(2):用例编写
  • ReactPress与WordPress:一场内容管理系统的较量
  • Android ART知多少?
  • UEFI PEI阶段的一些基本概念
  • Xilinx系FPGA学习笔记(八)FPGA与红外遥控
  • TensorFlow 笔记
  • 离线数仓DWD层
  • 【QT】定时器使用
  • 第R3周:LSTM-火灾温度预测:3. nn.LSTM() 函数详解
  • 鸿蒙之Hello Word 遇坑总结 mac系统 不能预览 提示 Only files in a module can be previewed 解决办法
  • 分贝转换 1 mVpp = 9.03dBmV
  • RISCV64应用符号解析的实现机制
  • 响应式CSS 媒体查询——WEB开发系列39
  • 艾里斑(Airy Disk)与瑞利判据(Rayleigh criterion)
  • 2024上半年国产操作系统卖疯了!麒麟4.9亿,统信1.9亿!
  • 41.在 CSS 中使用 clamp() 实现响应式排版
  • 【智路】智路OS Perception Fusion Service
  • 暗界正方形之谜
  • 复杂情感识别系统
  • CAD_Electrical 2022使用记录
  • 【加密算法基础——RSA加密特点分析及解密方式】
  • Java面向对象六大设计原则总结(超级详细,附有代码、图解以及案例)
  • 深入理解Python中的“_,”:一个实用的语法特性
  • 神经网络通俗理解学习笔记(3)注意力神经网络