多态的学习

1多态的基本概念

多态分为两类:

  • 静态多态:函数重载 和 运算符重载, 复用函数名
  • 动态多态:派生类和虚函数实现运行时的多态

静态多态和动态多态的区别:

  • 静态多态的函数地址早绑定- 编译阶段确定函数地址
  • 动态多态的函数地址晚绑定-运行阶段确定函数地址

动态多态满足条件:

  1. 得有继承关系
  2. 子类重写父类的虚函数(重写:函数返回值类型 函数名称 参数列表 完全相同)

动态多态的使用:
父类的指针或者引用 指向子类对象

#include <iostream>
using namespace std;
class Animal
{
public:
    virtual void speak()  //虚函数,地址不绑定为Animal
    {
        cout<<"动物在说话"<<endl;
    }
};
class Cat:public Animal
{
public:
    void speak()
    {
        cout<<"小猫在说话"<<endl;
    }
};
//地址早绑定,所以是动物在说话
void speak(Animal &animal)//引用
{
    animal.speak();
}
void test1()
{
    Cat cat;
    speak(cat);
}
int main() {
    test1();
    return 0;
}

2多态的原理剖析

#include <iostream>
using namespace std;
class Animal
{
public:
     virtual void speak()  //虚函数,地址不绑定为Animal
    {
        cout<<"动物在说话"<<endl;
    }
};
class Cat:public Animal
{
public:
    void speak()
    {
        cout<<"小猫在说话"<<endl;
    }
};
//地址早绑定,所以是动物在说话
void speak(Animal &animal)
{
    animal.speak();
}
void test1()
{
    Cat cat;
    speak(cat);
}
void test2()
{
    cout<<"sizeof Animal="<<sizeof(Animal)<<endl;//去掉virtual空类大小为1
    //加上virtual为8 多了一个指针
    //vfptr :virtual function pointer 虚函数(表)指针
    //指向虚函数表 vftable virtual function table
    //表的内部记录虚函数的地址, &Animal::speak
    //子类继承后,会同时继承虚函数指针和表,
    //当子类重写父类的虚函数,子类的虚函数表内会替换成子类的虚函数地址 &Cat::speak
    //当父类的指针或者引用指向子类对象时候,发生多态
    //Animal &animal =cat;
    //animal.speak;
}
int main() {
    //test1();
    test2();
    return 0;
}

3多态-案例1-计算器类

案例描述:
分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类

多态的优点:

  • 代码组织结构清晰
  • 可读性强
  • 对于前期和后期的拓展和维护性高
#include <iostream>
#include <string>
using namespace std;
//普通写法
class Calculator
{
public:
    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;
        }
        //如果想拓展新功能,需要修改源码。
        //在真实的开发中 提倡 对拓展进行开放,对修改进行关闭。
    }
    int m_Num1;
    int m_Num2;

};
void test01()
{
    Calculator c;
    c.m_Num1=10;
    c.m_Num2=10;
    cout<<c.m_Num1<<"+"<<c.m_Num2<<"="<<c.getResult("+")<<endl;
    cout<<c.m_Num1<<"-"<<c.m_Num2<<"="<<c.getResult("-")<<endl;
    cout<<c.m_Num1<<"*"<<c.m_Num2<<"="<<c.getResult("*")<<endl;

}
//--------------------------------------------------------
//利用多态
//实现计算器的抽象类
class AbstractCaculator
{
public:
    virtual int getResult()
    {
        return 0;
    }
    int m_Num1;
    int m_Num2;

};
class AddCaculator:public AbstractCaculator
{
public:
    int getResult()
    {
        return m_Num2+m_Num1;
    }

};
class SubCaculator:public AbstractCaculator//subtraction减法
{
public:
    int getResult()
    {
        return m_Num2-m_Num1;
    }

};
class MulCaculator:public AbstractCaculator
{
public:
    int getResult()
    {
        return m_Num2*m_Num1;
    }

};
void test02()
{
    //多态使用条件
    //父类指针或者引用指向子类对象
    AbstractCaculator *abc =new AddCaculator;//堆区
    abc->m_Num1=10;
    abc->m_Num2=10;
    cout<<abc->m_Num1<<"+"<<abc->m_Num2<<"="<<abc->getResult()<<endl;
    delete abc;//数据释放,指针类型没变
    abc=new SubCaculator;
    abc->m_Num1=10;
    abc->m_Num2=10;
    cout<<abc->m_Num1<<"-"<<abc->m_Num2<<"="<<abc->getResult()<<endl;
    delete abc;
}


int main()
{
    //test01();
    test02();
}

4纯虚函数和抽象类

在多态中,父类中虚函数的实现是毫无意义的,通常会调用子类重写的内容。
因此可以将虚函数改为纯虚函数

纯虚函数语法:virtual 返回值类型 函数名 (参数列表)=0;

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

抽象类特点:

  • 无法实例化对象
  • 子类必须重写抽象类中的纯虚函数,否则子类也属于抽象类。
#include <iostream>
#include <string>
using namespace std;

//抽象类
class Base
{
public:
    //纯虚函数
    virtual void func()=0;
};
class Son:public Base
{
public:
    void func()
    {
        cout<<"func()"<<endl;

    }
};
void test01()
{
    Base *base = new Son;
    base->func();
}
int main ()
{
    test01();
}

5多态-案例2-制作饮品。

案例描述:
制作饮品大体流程:煮水-》冲泡-〉倒入杯中-》加入辅料

6虚析构和纯虚析构

多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构代码。
解决方式:将父类的析构函数改为虚析构或者纯虚析构

虚析构和纯虚析构共性:

  • 都可以解决父类指针释放子类对象。
  • 都需要具体的函数实现。

区别:

  • 如果是纯虚虚构,该类属于抽象类,无法实例化对象。

虚析构语法:
virtual ~类名()
纯虚析构语法:
virtual ~类名()=0;
类名::~类名(){}

7多态案例3-电脑组装

案例描述:
电脑的主要组成部件为CPU(计算),显卡(显示),内存条(存储)。
将每个零件封装出抽象基类,并且提供不同的厂商生产不同的零件,例如Intel厂商和Lenovo厂商。
创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口。
测试时组装三台不同电脑工作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值