多态、虚函数表、虚指针、动态绑定

多态

1、方法重写:子类可以重写父类的函数
2、向上类型转换:用一个父类指针指向子类对象的时候,假如调用的是虚函数,会自动暂时的将该指针转换为子类类型

虚函数的作用就是指针类型转换,但即使没有虚函数也可以重写方法

虚函数表 与虚函数

虚表是什么:只是一个数组,里面的每个元素存放的是虚函数的地址。
虚指针是什么:只是一个指针,指向虚表。

需要特别注意的是:虚表是对于类而言的,虚指针则是针对对象而言的。

也就是说,可以认为虚表内存存在于类内存中(代码区),每一个类只需要一份就可以了。虚指针则存在于对象的内存(堆栈区)里,每一个对象就有一个虚指针。假如某个类实例化了10000个对象,那么虚指针就要占用10000*8字节(假设每个指针占用8字节),而虚表的占用内存则完全不变。

注意:每一个实例化的对象里面都有一个虚指针,要是编译器发现这个对象要调用虚函数,虚指针就会指向该对象类的虚函数表,去寻找虚函

我们只要当p指向父类对象的时候,指向的是父类的vptr;当p指向父类对象的时候,指向的是子类的vptr

在这里插入图片描述

虚函数表的具体实现

当一个类里存在虚函数时,编译器会为类创建一个虚函数表vtable,虚函数表是一个数组,数组的元素存放的是类中虚函数的地址。
编译器还会在**对象的存储空间中安插一个指针vfptr,**指向虚函数表数组的起始位置
每一个有虚函数的类都有一个虚函数表,虚函数是整个类所共有的,虚函数表存储在对象内存最开始的位置。如果子类继承了多个父类,并且父类有虚函数,则子类要存储多个虚函数指针。

请添加图片描述
1、基类base里面最初的虚函数表
请添加图片描述
2、当子类Node继承基类base但是没有将虚函数重写,Node的虚函数表
请添加图片描述
3、当子类Node覆盖了基类的虚函数,Node的虚函树表
父类被覆盖的函数f(),都被替换为子类的虚函数f()
请添加图片描述

动态绑定

//基类
class Base{
public:
    virtual void func();
protected:
    int m_a;
    int m_b;
};
void Base::func(){ cout<<"调用基类"<<endl; }

//派生类
class Derived: public Base{
public:
    void func();
private:
    int m_c;
};
void Derived::func(){ cout<<"调用子类"<<endl; }
int main(){
    Base *p;
    int n;

    cin>>n;//用户操作不同,p指向的对象类型不同
    
    if(n <= 100){
        p = new Base();
    }else{
        p = new Derived();
    }
    cout<<typeid(*p).name()<<endl;
    return 0;
}

输入 45,运行结果为:
45↙
基类

输入 130,运行结果为:
130↙
子类

同一个虚函数,会根据我们指针指向不同对象去对找到对应的虚函数表,然后绑定我们需要的虚函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值