c++ 语法多态

news2024/11/25 22:42:00

多态分为两类

静态多态:函数重载和运算符重载属于静态多态复用函数名

动态多态: 派生类和虚函数实现运行时多态。

静态多态和动态多态区别

静态多态的函数地址早绑定:编译阶段确定函数地址

动态多态函数地址晚绑定:运行阶段确定函数位置

class AnimalBase{
public:
    int m_age;
    // 虚函数 函数在运行阶段绑定
    virtual void speek() {
        cout << "AnimalBase speek" <<  endl;
    }
    
};

class Dog : public AnimalBase
{
    void speek() override {
        cout << "dog speek" <<  endl;
    }
};

class Pag : public AnimalBase {
    void speek() override {
        cout << "Pag speek" <<  endl;
    }
};
//
void doWork(AnimalBase &animal) {
    animal.speek();
}

void test58() {
    Pag p;
    doWork(p);
    Dog d;
    doWork(d);
}
int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    test58();
    std::cout << "end!\n";
    return 0;
}

动态多态满足条件

1.有继承关系

2.重写父类中的虚函数 (返回值 函数名 参数列表 完全一致)

动态多态使用

父类的指针或者引用 指向子类对象。

 

多态原理

当类中有虚函数的时候 类里面会有一个虚函数表指针。指向虚函数表

vfptr v virtual f function ptr 指针

当子类继承于父类的时

 没有重写虚函数

子类会从父类继承虚函数表

当重写后

子类虚函数表内部会替换成子类虚函数表地址

当父类的指针或者引用指向子类的时候就发生了多态

上边是父类的 内部结构图

下边是没有重写时类的内部结构图 

重写后类的内部结构图 

 多态案例

多态的好处

1.组织结构清晰

2.可读性强

#include <iostream>
#include <string>
using namespace std;
class AbstureCalculator {
public:
    int m_num1;
    int m_num2;
    virtual int getResult() {
        return 0;
    };
};

class SumCalculator : public AbstureCalculator {
    int getResult() override {
        return m_num1 + m_num2;
    }
};

class MinusCalculator : public AbstureCalculator {
    int getResult() override {
        return m_num1 - m_num2;
    }
};
class MulCalculator : public AbstureCalculator {
    int getResult() override {
        return m_num1 * m_num2;
    }
};

void test60() {
    AbstureCalculator *calculator = new SumCalculator;
    calculator->m_num1 = 100;
    calculator->m_num2 = 2000;
    cout << calculator->getResult() << endl;
    delete calculator;
    calculator = new MinusCalculator;
    calculator->m_num1 = 2000;
    calculator->m_num2 = 100;
    cout << calculator->getResult() << endl;
    delete calculator;

    calculator = new MulCalculator;
    calculator->m_num1 = 2000;
    calculator->m_num2 = 100;
    cout << calculator->getResult() << endl;
    delete calculator;

}


// 普通写法
class Calculator {
    
public:
    int m_num1;
    int m_num2;
    int getResult(string oper) {
        if (oper == "+") {
            return m_num1 + m_num2;
        } else if (oper == "-") {
            return m_num1 - m_num2;
        } else if (oper == "*") {
            return m_num1 * m_num2;
        } else if (oper == "/") {
            return m_num1 / m_num2;
        }
        return  0;
    };
};
void test53() {
    Calculator  c;
    c.m_num1 = 100;
    c.m_num2 = 200;
    c.getResult("*");
}

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    test53();
    test60();
    std::cout << "end!\n";
    return 0;
}

纯虚函数和抽象类

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

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

纯虚函数的语法

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

当类中有了纯虚函数 这个类称为抽象类。

抽象类特点

无法实例化对象。

子类必须重写抽象类中的纯虚函数,否则也属于抽象类


#include <iostream>
#include <string>
using namespace std;
class Super {
public:
    //纯虚函数
    //只要有一个纯虚函数 这个类称为抽象类
    //抽象类特点
    //1.无法实例化对象
    //2.抽象类必须重写纯虚函数否则也是抽象类
    virtual void func() = 0;
};
class Son : public Super {
public:
    void func() override {
        cout << "virtual" << endl;
    }
};

void test61() {
    //Super s;//Variable type 'Super' is an abstract class
    Son s;
    s.func();
}
int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    test61();
    std::cout << "end!\n";
    return 0;
}
#include <iostream>
#include <string>
using namespace std;
class AbstractDrink{
public:
    virtual void boil() = 0;
    virtual void brew() = 0;
    virtual void cup() = 0;
    virtual void putSome() = 0;
    void makeDrink() {
          boil();
          brew();
          cup();

    }
    virtual ~AbstractDrink(){

    }
};
class coffe : public AbstractDrink {
public:
    void boil() override  {
        cout << "煮水" << endl;
    }
    void brew() override {
        cout << "加入coffe" << endl;

    }
    void cup() override {
        cout << "放入杯子" << endl;
    }
    void putSome() override {
        cout << "加入辅料 " << endl;
    }
};
class Tea : public AbstractDrink {
public:
    void boil() override  {
        cout << "煮水" << endl;
    }
    void brew() override {
        cout << "加入茶叶" << endl;

    }
    void cup() override {
        cout << "放入杯子" << endl;
    }
    void putSome() override {
        cout << "加入柠檬 " << endl;
    }
};

void doMakeDrink(AbstractDrink *drink) {
    drink->makeDrink();
}
void test62() {
    AbstractDrink *drink = new coffe;
    doMakeDrink(drink);
    delete drink;
    drink = new Tea;
    doMakeDrink(drink);
    delete drink;
//    Delete called on 'AbstractDrink' that is abstract but has non-virtual destructor
}
int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    test62();
    std::cout << "end!\n";
    return 0;
}

虚析构和纯虚析构

解决父类指针指向子类的时候 释放不干净的问题

若子类中没有堆区数据 可以不写虚析构或纯虚析构

拥有纯虚析构函数的类也属于抽象类

#include <iostream>
using namespace std;
class AbstractA {
public:
    int *m_a;
    virtual void info() = 0;
    AbstractA(){
        cout << "AbstractA init" << endl;
    }
//    // 虚析构
//    virtual~AbstractA(){//Delete called on 'AbstractA' that is abstract but has non-virtual destructor
//        cout << "~AbstractA()" << endl;
//    }
    //纯虚析构 必须要实现
    virtual ~AbstractA() = 0;
};
AbstractA::~AbstractA(){
    cout << "AbstractA::~AbstractA()" << endl;
}

class ClassB: public AbstractA {
public:
    void info() override {
        cout << *m_a << endl;
    }
    ClassB(int a) {
        m_a = new int(a);
        cout << "ClassB init" << endl;
    }
    ~ClassB(){
        if (m_a != nullptr) {
            delete m_a;
        }
        cout << " ~ClassB()" << endl;
    }
};
void test63() {
    AbstractA *a = new ClassB(12);
    a->info();
    delete a;
}
int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    test63();
    std::cout << "end!\n";
    return 0;
}


#include <iostream>
#include "mathutil.hpp"
#include <string>
#include "People.hpp"
#include "Phone.hpp"
using namespace std;
class  Cpu{
public:
    virtual void calculate() = 0;
    virtual ~Cpu(){
        cout << "~Cpu" << endl;
    }
};
class  VideoCard{
public:
    virtual void display() = 0;
    virtual ~VideoCard(){
        cout << "~VideoCard" << endl;

    }

};
class  Memory{
public:
    virtual void storege() = 0;
    virtual ~Memory(){
        cout << "~Memory" << endl;
    }

};
class Computer{
private:
    Cpu *m_cpu;
    VideoCard *m_videoCard;
    Memory *m_memory;
public:
    Computer(Cpu *cpu,VideoCard *card,Memory *m) {
        m_cpu = cpu;
        m_videoCard = card;
        m_memory = m;
    };
    ~Computer(){
        if(m_cpu != nullptr) {
            delete m_cpu;
        }
        
        if(m_videoCard != nullptr) {
            delete m_videoCard;
        }
        if(m_memory != nullptr) {
            delete m_memory;
        }

    }
    void work() {
        m_cpu -> calculate();
        m_videoCard -> display();
        m_memory -> storege();
    }
};
class InterCpu: public Cpu {
public:
    void calculate() override {
        cout << "inter cpu 开始工作了" << endl;
    }
    virtual ~InterCpu(){
        cout << "~InterCpu" << endl;
    }

};
class InterVideoCard : public VideoCard {
public:
    void display() override {
        cout << "inter 显卡 开始工作了" << endl;
    }
    virtual ~InterVideoCard(){
        cout << "~InterVideoCard" << endl;
    }

};
class InterMemort : public Memory {
    void storege() override {
        cout << "inter 内存条 开始工作了" << endl;
    }
    virtual ~InterMemort(){
        cout << "~InterMemort" << endl;
    }

};


class DellCpu: public Cpu {
public:
    void calculate() override {
        cout << "Dell cpu 开始工作了" << endl;
    }
    virtual ~DellCpu(){
        cout << "~DellCpu" << endl;
    }

};
class DellVideoCard : public VideoCard {
public:
    void display() override {
        cout << "Dell 显卡 开始工作了" << endl;
    }
    virtual ~DellVideoCard(){
        cout << "~DellVideoCard" << endl;
    }

};
class DellMemory : public Memory {
    void storege() override {
        cout << "Dell 内存条 开始工作了" << endl;
    }
    virtual ~DellMemory(){
        cout << "~DellMemory" << endl;
    }

};

void test64() {
    Cpu *c = new InterCpu;
    VideoCard *v = new InterVideoCard;
    Memory *m = new InterMemort;
    
    Computer *cvm = new  Computer(c,v,m);
    cvm->work();
    delete cvm;
    
    
   c = new DellCpu;
   v = new DellVideoCard;
   m = new DellMemory;
   cvm = new  Computer(c,v,m);
   cvm->work();
   delete cvm;
}

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    test64();
    std::cout << "end!\n";
    return 0;
}

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

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

相关文章

esp8266 步骤

安装驱动 http://arduino.esp8266.com/stable/package_esp8266com_index.json oled库 esp8266-oled-ssd1306

01-Datahub是什么?

Datahub是LinkedIn开源的基于现代数据栈的元数据管理平台&#xff0c;原来叫做WhereHows 。经过一段时间的发展datahub于2020年2月在Github开源。 官网地址为&#xff1a;A Metadata Platform for the Modern Data Stack | DataHub 源码地址为&#xff1a;GitHub - datahub-p…

飞天使-k8s知识点12-kubernetes散装知识点1-架构有状态

文章目录 k8s架构图有状态和无状态服务 资源和对象对象规约和状态 资源的对象-资源的分类 k8s架构图 有状态和无状态服务 区分有状态和无状态服务有利于维护yaml文件 因为配置不同资源和对象 命令行yaml来定义对象对象规约和状态 规约 spec 描述对象的期望状态状态 status 对…

ArcGIS学习(三)数据可视化

ArcGIS学习(三)数据可视化 1.矢量数据可视化 需要提前说明的是,在ArcGIS中,所有的可视化选项设置都是在“图层属性”对话框里面的“符号系统”中实现的。 对于矢量数据的可视化,主要有四种可视化方式: 按“要素”可视化按“类别”可视化按“数量”可视化按“图表”可视…

【证书管理】实验报告

证书管理实验 【实验环境】 ISES客户端 【实验步骤】 查看证书 查看证书详细信息 选择任意证书状态&#xff0c;在下方“证书列表”中出现符合要求的所有证书。在“证书列表”中点击要查看证书&#xff0c;在右侧“证书详细信息”栏出现被选证书信息。 上述操作如图1.2.…

PS一键磨皮插件Delicious Retouch for mac中文 支持PS2024

Delicious Retouch for Mac是一款优秀的Photoshop插件&#xff0c;专注于人像修饰。以下是该插件的一些主要特点和功能&#xff1a; 软件下载&#xff1a;Delicious Retouch for mac中文 支持PS2024 人像修饰工具&#xff1a;Delicious Retouch专注于人像修饰&#xff0c;提供了…

编程实例分享,物流车辆调度管理系统软件教程

编程实例分享&#xff0c;物流车辆调度管理系统软件教程 一、前言 以下教程以 佳易王物流车辆调度管理系统软件V16.0为例说明 如上图&#xff0c;左侧为 导航栏&#xff0c;在系统设置里可以设置打印参数 如上图&#xff0c;填写托运方&#xff0c;货物&#xff0c;司机等信…

idea 快捷键ctrl+shift+f失效的解决方案

文章目录 搜狗输入法快捷键冲突微软输入法快捷键冲突 idea的快捷键ctrlshiftf按了没反应&#xff0c;理论上是快捷键冲突了&#xff0c;检查搜狗输入法和微软输入法快捷键。 搜狗输入法快捷键冲突 不需要简繁切换的快捷键&#xff0c;可以关闭它&#xff0c;或修改快捷键。 微…

乐意购项目前端开发 #7

一、购物车 本地购物车 创建cartStore.js文件 创建cartStore.js文件, 将购物车列表数据存在pinia中 import { ref, computed } from "vue"; import { defineStore } from "pinia"; import { useUserStore } from "./user"; import {insertCart…

【鸿蒙】大模型对话应用(四):页面发起请求实现对话能力

Demo介绍 本demo对接阿里云和百度的大模型API&#xff0c;实现一个简单的对话应用。 DecEco Studio版本&#xff1a;DevEco Studio 3.1.1 Release HarmonyOS SDK版本&#xff1a;API9 关键点&#xff1a;ArkTS、ArkUI、UIAbility、网络http请求、列表布局、层叠布局 定义接…

自动驾驶IPO第一股及商业化行业标杆 Mobileye

一、Mobileye 简介 Mobileye 是全球领先的自动驾驶技术公司&#xff0c;成立于 1999 年&#xff0c;总部位于以色列耶路撒冷。公司专注于开发视觉感知技术和辅助驾驶系统 (ADAS)&#xff0c;并在自动驾驶领域处于领先地位。Mobileye 是高级驾驶辅助系统&#xff08;ADAS&#…

13. Threejs案例-绘制3D文字

13. Threejs案例-绘制3D文字 实现效果 知识点 FontLoader 一个用于加载 JSON 格式的字体的类。 返回 font&#xff0c;返回值是表示字体的 Shape 类型的数组。 其内部使用 FileLoader 来加载文件。 构造器 FontLoader( manager : LoadingManager ) 参数类型描述managerLo…

从零开始手写mmo游戏从框架到爆炸(二)— 核心组件抽离与工厂模式创建

上一章我们已经完成了一个基本netty的通信&#xff0c;但是netty的启动很多代码都是重复的&#xff0c;所以我们使用工厂模式来生成不同的ServerBootstrap。 首先创建一个新的组件core组件&#xff0c;和common组件&#xff0c;主要用于netty通信和工具类&#xff0c;从server…

day31 JS执行机制

目录 前言同步和异步JS执行机制 前言 JavaScript语言的一大特点是单线程。 JavaScript是为处理页面中用户的交互&#xff0c;以及操作DOM而诞生的。比如对某个DOM元素进行添加和删除操作&#xff0c;不能同时进行&#xff0c;应该先进行添加再继续删除。 示例&#xff08;解…

服务器性能监控管理方法及工具

服务器是组织数据中心的主干&#xff0c;无论是优化的用户体验&#xff0c;还是管理良好的资源&#xff0c;服务器都能为您完成所有工作&#xff0c;保持服务器随时可用和可访问对于面向业务的应用程序和服务以最佳水平运行至关重要。 理想的服务器性能需要主动监控物理和虚拟…

为电子表格嵌入数据库,Excel/WPS一键升级为管理系统

将Excel表格转化为管理系统&#xff0c;这款工具能够实现只需导入表格数据&#xff0c;即可自动生成相应的软件和APP。 表格办公的烦恼&#xff0c;有遇到吧&#xff1f; 对于具有一定规模的企业而言&#xff0c;各类表格如同繁星般众多&#xff0c;既有日常使用的常规表格&a…

力扣刷题之旅:进阶篇(一)

力扣&#xff08;LeetCode&#xff09;是一个在线编程平台&#xff0c;主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目&#xff0c;以及它们的解题代码。 --点击进入刷题地址 题目1&#xff1a;三数之和 题目描述&#xff1a; 给定一个包含n个…

轻型民用无人机驾驶航空器安全操控——理论考试多旋翼部分笔记

今天已经可以在线考取轻型民用无人机驾驶航空器执照了&#xff0c;所以我也在在线观看完视频之后整理了如下的知识点&#xff0c;所有知识点全部来自UOM平台。 目录 航空器知识 &#xff08;1&#xff09;多旋翼民用无人驾驶航空器螺旋桨的作用 &#xff08;2&#x…

[office] Excel表格中的日期怎么快速标注双休日- #经验分享#职场发展#职场发展

Excel表格中的日期怎么快速标注双休日? Excel表格中的日期怎么快速标注双休日&#xff1f;excel表格中的数据想要标注出双休日&#xff0c;该怎么给双休日填充黄色背景呢&#xff1f;下面我们就来看看详细的教程&#xff0c;需要的朋友可以参考下 excel表格中的数据&#xff…

ReactNative实现的横向滑动条

OK&#xff0c;我们先看下效果图 注意使用到了两个库 1.react-native-linear-gradient 2.react-native-gesture-handler ok&#xff0c;我们看下面的代码 import {Image, TouchableWithoutFeedback, StyleSheet, View} from react-native; import LinearGradient from reac…