C++特性之多态,三个多态案例

多态
    多态的基本概念
     多态是C++面向对象三大特性之一
    多态分为两类
        静态多态:函数重载 和 运算符重载 属于 静态多态,复用函数名
        动态多态:派生类 和 虚函数 实现运行时多态
     静态多态和动态多态区别:
        (1)静态多态的函数地址早绑定  –  编译阶段确定函数地址
        (2)动态多态的函数地址晚绑定  –  运行阶段确定函数地址
下面通过案例进行讲解多态
#include<iostream>
using namespace std;

//多态
class Animal{    
public:
    virtual void speak(){    //加上virtual后,函数变为虚函数
        cout << "动物在说话" << endl;
    }
};
class Cat :: public Animal{
public:
    void speak(){
        cout << "小猫在说话" << endl;
    }
}
18行:void doSpeak(Animal &animal){    //Animal &animal = cat  父类的引用在指向子类的对象
    //静态多态
    animal.speak();    //这里调用的是父类的speak()函数,也就是动物在说话,因为这里函数的地址是早绑定的,也就是一开始就绑定了父类中的speak()函数,在编译阶段就确定了函数地址
    //如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定,解决方法,在speak()函数前加virtual,将函数更改为虚函数
    //动态多态
    animal.speak();  //这里就是猫在说话


}
void test01(){
    Cat cat;
    doSpeak(cat);    
}
int main(){
    test01();
    system("pause") ;
    return 0;
}

总结:
    动态多态满足条件
    1、有继承关系
    2、子类要重写父类的虚函数(子类中重写函数时可以不用加virtual,但是父类中必须加)
    
    动态多态使用
        父类的指针或者引用,执行子类对象(也就是第18行的代码)
多态的底层原理:
#include<iostream>
using namespace std;


//多态
class Animal{    
public:
    void speak(){    //加上virtual后,函数变为虚函数
        cout << "动物在说话" << endl;
    }
};
class Cat :: public Animal{
public:
    void speak(){
        cout << "小猫在说话" << endl;
    }
}
void doSpeak(Animal &animal){    //Animal &animal = cat  父类的引用在指向子类的对象
    animal.speak();   
    animal.speak();  
}
void test01(){
    Cat cat;
    doSpeak(cat);    
}
void test02(){
    cout << "sizeof Animal = " << sizeof(Animal) << endl; //现在Animal类中只有一个非静态的成员函数,他不属于类的对象,是分开存储的,那Animal相当于是一个空类,那么他的大小就是sizeof(Animal) = 1;
    //如果加上virtual关键字,那么sizeof(Animal) = 4,这4个字节是一个指针,如图1详解
}
int main(){
    test01();
    test02();
    system("pause") ;
    return 0;
}

图1
子类将父类拷贝一份之后speak函数的入口地址是Animal类中的speak函数地址,&Cat :: speak 这个代码将speak函数的入口地址变为Cat对象的speak函数地址,然后会将原来子类中&Animal::speak函数的地址覆盖掉,如下图所示
这里就相当于子类将父类的虚函数给替换掉了,但是父类中的虚函数并没有发生改变
当父类的指针或者引用指向子类对象的时候,发生多态
Animal *animal = cat ;
animal.speak();
由于指向的是一个cat对象,那么他会去cat的虚函数表中去找speak函数,这是在运行阶段
 
多态案例一-计算器类
    案例描述:
        分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类
     多态的优点:
        (1)代码组织结构清晰
        (2)可读性强
        (3)利于前期和后期的扩展以及维护
include<iostream>
using namespace std;

//分别利用普通写法和多态技术实现计算器
//普通写法
class Calculator{
public:
    int getResu1t(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;
        }
        //如果想扩展新的功能,需要修改源码
    int m_Num1 ;//操作数1
    int m_Num2;//操作数2
};

void test01(){
//创建计算器对象
    Caiculator c;
    c.m_Num1 = 10;
    c.m_Num2 = 10;
    cout << c.m_Num1 << " + " << c.m_Num2〈<<" = " << c.getResult("+") << end1;//20
     cout << c.m_Num1 << " - " << c.m_Num2〈<<" = " << c.getResult("-") << end1;//0
    cout << c.m_Num1 << " * " << c.m_Num2〈<<" = " << c.getResult("*") << end1;//100
}

//利用多态实现计算器
//实现计算器抽象类
class AbstractCalculator
public:
    virtual int getResult(){
        return 0;
    }
    int m_Num1;
    int m_Num2;
};
//加法计算器类
class AddCalculator : public AbstractCalculator{
public:
    virtual int getResult(){
        return m_Num1 + m_Num2;
    }
}
//减法计算器类
class SubCalculator : public AbstractCalculator{
public:
    virtual int getResult(){
        return m_Num1 - m_Num2;
    }
}
void test02(){
    //多态使用条件
    //父类指针或者引用指向子类对象
    AbstractCalculator * abc = new AddCalculator;
    abc->m_Num1 = 10;
    abc->m_Num2 = 10;
    cout << abc->m_Num1 <<"+"<< abc->m_Num2<< " = " << abc->getResult() << endl;
    //用完记得销毁
    delete abc;
    
    abc = new SubCalculator;
    abc->m_Num1 = 10;
    abc->m_Num2 = 10;
    cout << abc->m_Num1 <<"-"<< abc->m_Num2<< " = " << abc->getResult() << endl;
    delete abc;
}
int main(){
    test01();
    test02();
    system("pause");
    return 0;
}
多态带来的好处:
    1、组织结构清晰
    2、可读性强
    3、对于前期和后期扩展以及维护性高
案例三:

案例描述:

        电脑主要组成部件为CPU(用于计算),显卡(用于显示),内存条(用于存储)

        将每个零件封装出抽象基类,并且提供不同的厂商生产不同的零件,例如Intel厂商和Lenovo厂商创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口

        测试时组装三台不同的电脑进行工作

#include <iostream>
#include <string>
using namespace std;

class CPU{
public:
    virtual void run_CPU() = 0;
};
class Screem{
public:
    virtual void run_screem() = 0;
};
class RAM{
public:
    virtual void run_ram() = 0;
};
class Computer{
public:
    Computer(CPU *cpu,Screem *screem,RAM *ram){
        m_CPU = cpu;
        m_screem = screem;
        m_RAM = ram;
    }
    ~Computer(){
        if(m_CPU == NULL){
            delete m_CPU;
            m_CPU = NULL;
        }
        if(m_screem == NULL){
            delete m_screem;
            m_screem = NULL;
        }
        if(m_RAM == NULL){
            delete m_RAM;
            m_RAM = NULL;
        }
    }
    void dowork(){
        m_CPU->run_CPU();
        m_screem->run_screem();
        m_RAM->run_ram();
    }
private:
    CPU *m_CPU;
    Screem *m_screem;
    RAM *m_RAM;
};
ostream &operator <<(ostream &cout,string &string){
    cout << string.c_str()<<endl;
    return cout;
}
class Inter_CPU:public CPU{
public:
    virtual void run_CPU(){
        cout << " Inter_CPU is running!"<<endl;
    }
};
class Inter_Screem:public Screem{
public:
    virtual void run_screem(){
        cout <<" Inter_SCREEM is running!"<<endl;
    }
};
class Inter_RAM:public RAM{
public:
    virtual void run_ram(){
        cout << " Inter_RAM is running!"<<endl;
    }
};
void test01(){
    Inter_CPU inter_cpu;
    Inter_Screem inter_screem;
    Inter_RAM inter_ram;
    CPU *F_CPU = &inter_cpu;
    Screem *F_SCREEM = &inter_screem;
    RAM *F_RAM = &inter_ram;
    Computer(F_CPU,F_SCREEM,F_RAM).dowork();
}
int main(){
    test01();
    system("pause");
    return 0;
}

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值