多态---01

多态

多态是C++面向对象的三大特性之一

多态分为两种:

  • 静态多态:重载—函数重载与运算符重载
  • 动态多态:派生类和虚函数

静态多态与动态多态的区别:函数地址的绑定时机不同

  • 静态多态的函数地址早绑定,即在编译阶段确定函数地址
  • 动态多态的函数地址晚绑定,即在运行阶段确定函数地址
#include <iostream>
using namespace std;

class A
{
public:
    virtual void speak()
    {
        cout << "A::speak" << endl;
    }
};
class B : public A
{
public:
    void speak()
    {
        cout << "B::speak" << endl;
    }
};

class C : public A
{
public:
    void speak()
    {
        cout << "C::speak" << endl;
    }
};

// 父类的引用指向子类的对象
// 地址早绑定,在编译阶段确定函数地址
void doTest(A &a)
{
    a.speak();
}
void Test()
{
    B b;
    doTest(b);

    C c;
    c.speak();
}
int main()
{
    Test();
    system("pause");
    return 0;
}

动态多态的满足条件

  1. 具有继承关系

  2. 子类必须重写父类的虚函数

    重写:函数名,参数个数,类型,顺序必须完全相同

动态多态的使用

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

多态的原理

由于写了一个虚函数,类内部结构发生改变,多了一个虚函数指针(vfptr),虚函数指针指向一个虚函数表(vftable),当子类自己重写虚函数后,会替换子类自己的虚函数表里的内容 ,当用父类的引用指向子类对象,由于本身还是一个子类对象,所以当子类调用speak函数时候,会从子类的虚函数表中找函数入口地址。

工具支持:Developer Command Prompt for VS 2019

class A
{
public:
    void speak()
    {
        cout << "A::speak" << endl;
    }
};

请添加图片描述

class A
{
public:
    virtual void speak()
    {
        cout << "A::speak" << endl;
    }
};

请添加图片描述

B没有重写A中speak函数

class A
{
public:
    virtual void speak()
    {
        cout << "A::speak" << endl;
    }
};
class B : public A
{
};

请添加图片描述

B重写A中speak函数

class A
{
public:
    virtual void speak()
    {
        cout << "A::speak" << endl;
    }
};
class B : public A
{
public:
    void speak()
    {
        cout << "B::speak" << endl;
    }
};

请添加图片描述

纯虚函数和抽象类

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

因此可以将虚函数改为纯虚函数

纯虚函数语法:

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

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

抽象类特点:

  • 无法实例化对象
    数和抽象类

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

因此可以将虚函数改为纯虚函数

纯虚函数语法:

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

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

抽象类特点:

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

//抽象类
class A
{
public:
    //纯虚函数
    //只要有一个纯虚函数,则个类称为抽象类
    // 抽象类特点:
    // 1.无法实例化兑现
    // 2.抽象类的子类必须重写父类中的纯虚函数,否则也属于抽象类
    //
    virtual void speak() = 0;
};
class B :public A
{
public:
    virtual void speak()
    {
        cout << "B::speak" << endl;
    }
};
void Test01()
{
    //报错 :
    // 不允许使用抽象类类型“A”的对象:
    // 函数“A.speak”是纯虚拟函数

    //A a;
    //new A;
}
void Test02()
{
    //B中没有重写speak函数时,如果创建对象,则会报错。
    //不允许使用抽急类类型“B”的对象:
    //纯虚拟 函数“A : speak”没有强制替代项
    //重写之后
    B b;
    B* bb = new(B);
    bb->speak();

}
int main()
{
    
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Exile_001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值