• C++纯虚函数和抽象类 & 制作饮品案例(涉及知识点:继承,多态,实例化继承抽象类的子类,多文件实现项目)


    一.纯虚函数的由来

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

    例如:

    #include
    
    using namespace std;
    
    class AbstractCalculator
    {
    public:
        int m_Num1;
        int m_Num2;
        virtual int getResult()
        {
            return 0;
        }
    };
    
    //加法计算器类
    class AddCalculator :public AbstractCalculator
    {
    public:
        int getResult()
        {
            return m_Num1+m_Num2;
        }
    
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    AbstractCalculator类是一个父类,里面 getResult()函数的实现是无意义的。
    因此可以将虚函数改为纯虚函数。
    
    • 1
    • 2

    二.纯虚函数语法

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

    三.抽象类及特点

    当类中有了纯虚函数,这个类也称为抽象类。
    
    • 1
    特点:
    1.抽象类无法实例化对象
    2.子类必须重写抽象类中的纯虚函数,否则也属于抽象类
    
    • 1
    • 2
    • 3

    四.制作饮品案例

    在这里插入图片描述

    4.1 单文件实现该案例

    创建c++文件 drinking.cpp

    #include
    
    using namespace std;
    
    class AbstractDrinking
    {
    public:
        //煮水
        virtual void Boil() = 0;
    
        //冲泡
        virtual void Brew() = 0;
    
        //倒入杯中
        virtual void PourInCup() = 0;
    
        //加入辅料
        virtual void PutSomething() = 0;
    
        //合并制作饮品流程
        void makeDrink()
        {
            Boil();
            Brew();
            PourInCup();
            PutSomething();
        }
    };
    
    
    
    //制作咖啡
    class Coffee: public AbstractDrinking
    {
    public:
    		// 由于父类已经声明过virtual,所以子类不必在函数前加virtual
        void Boil()
        {
            cout<<"煮农夫山泉1"<<endl;
        }    
        void Brew()
        {
            cout<<"冲泡咖啡1"<<endl;
        }
        void PourInCup()
        {
            cout<<"倒入杯中1"<<endl;
        }
        void PutSomething()
        {
            cout<<"加入糖和牛奶1"<<endl;
        }
    };
    
    int main()
    {
        AbstractDrinking* drink;
        // Coffee(); 像是函数的声明,所以一般实例化类时,当构造函数为空,则不用加括号,直接 Coffee。
        drink = new Coffee;
        // drink = new Coffee();
        drink->makeDrink();
        delete drink;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    linux端编译和运行:

    按 ctrl+` 弹出终端
    
    • 1

    输入如下命令:

    g++ drinking.cpp
    
    • 1

    生成一个可执行文件 a.out

    # 执行
    ./a.out
    
    • 1
    • 2

    4.1 多文件实现该案例

    4.1.1创建include文件,在里面创建类的头文件,用来声明函数

    AbstractDrinking.h
    #pragma once
    using namespace std;
    
    class AbstractDrinking
    {
    public:
        //煮水
        virtual void Boil() = 0;
    
        //冲泡
        virtual void Brew() = 0;
    
        //倒入杯中
        virtual void PourInCup() = 0;
    
        //加入辅料
        virtual void PutSomething() = 0;
    
        void makeDrink();
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    Coffee.h
    #pragma once
    #include
    using namespace std;
    
    
    //制作咖啡
    class Coffee: public AbstractDrinking
    {
    public:
        virtual void Boil();
    
        virtual void Brew();
        
        virtual void PourInCup();
        
        virtual void PutSomething();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.1.2 创建src文件,里面放置类的实现

    AbstractDrinking.cpp
    #include "AbstractDrinking.h"
        
    //合并制作饮品流程
    void AbstractDrinking::makeDrink()
    {
        Boil();
        Brew();
        PourInCup();
        PutSomething();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    Coffee.cpp
    #include "Coffee.h"
    #include
        
    void Coffee::Boil()
    {
        cout<<"煮农夫山泉"<<endl;
    }    
    void Coffee::Brew()
    {
        cout<<"冲泡咖啡"<<endl;
    }
    void Coffee::PourInCup()
    {
        cout<<"倒入杯中"<<endl;
    }
    void Coffee::PutSomething()
    {
        cout<<"加入糖和牛奶"<<endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.1.3 项目主目录创建main.cpp文件

    #include
    #include "AbstractDrinking.h"
    #include "Coffee.h"
    
    using namespace std;
    
    int main()
    {
        AbstractDrinking* drink;
        drink = new Coffee;
        // drink = new Coffee1();
        drink->makeDrink();
        delete drink;
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4.1.4 编译和执行

    g++ main.cpp src/AbstractDrinking.cpp src/Coffee.cpp -Iinclude -o b.out
    
    • 1
    ./b.out
    
    • 1
  • 相关阅读:
    DSPE-PEG-DBCO 磷脂-聚乙二醇-二苯并环辛炔 一种线性杂双官能聚乙二醇化试剂
    建立Logistic模型进行分析--课后习题3(多元统计分析)
    【PDF合并】利用 Python 合并 PDF 文件
    【漏洞复现】Progress Flowmon 命令注入漏洞CVE-2024-2389
    接口数据源变更,用 DeepDiff 测
    【1day】用友U8Cloud未授权访问漏洞学习
    千年版本修改小技巧
    spark相关网站
    一文搞懂Java线程中断协商机制,如何优雅中断一个正在运行的线程?
    深度残差网络的实现与编程
  • 原文地址:https://blog.csdn.net/qq_42864343/article/details/134506131