C++多态总结

多态概念:
多种形态,完成某个具体行为,不同的对象完成时可能会有不同的效果
多态:看实际指向的实体
非多态:看类型
例如:微信抢红包

多态的定义与实现
1.构成条件
多态是在不同继承关系的类对象,去调用同一函数,产生不同的行为。
必须通过基类的指针或者引用调用虚函数。
被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。

class Person {
public:
    virtual void BuyTicket() { cout << "买票-全价" << endl; }
};

class Student : public Person {
public:
    //基类的虚函数重写
    //子类中有和父类,函数接口完全相同(返回值、函数名、参数都相同)的虚函数(协变、析构重写除外)
    //**协变的返回值可以不同,但返回值必须是父子关系,父类返回值是父类,子类返回值是子类**
    virtual void BuyTicket() { cout << "买票-半价" << endl; }
};
//引用调用
void fun(Person& p) {
    p.BuyTicket();
}
//指针调用
void fun2(Person* p) {
    p->BuyTicket();
}

void test() {
    Person p;
    Student s;
    fun(p);
    fun(s);
    fun2(&p);
    fun2(&s);
}

注意:父类的函数必须是虚函数,否则就会形成函数隐藏,子类的函数加不加virtual都是函数重写,但最好都加上。

析构函数的重写
1.只要父类的析构函数是虚函数,则子类的析构函数和父类的析构函数构成重写
原因:编译器对继承关系下的所有类的析构函数的名字作了统一处理,保证了继承关系下所有类的析构函数同名,一般把析构函数的名称统一成desturctor

关键字
final
final定义的函数不能被重写,体现实现继承,一般在父类中使用

override
override定义的函数被强制重写,一般是强制子类函数重写父类的某一个虚函数,体现接口继承

抽象类定义
包含纯虚函数的类是抽象类,抽象类不能实例化,而抽象类的存在是为了实现多态,接口继承。
子类在继承抽象父类的时候,重写父类的纯虚函数,那么此时父类也会获得子类重写之后的函数效果
纯虚函数
没有函数体的虚函数

多态的基本原理

class Car{
public:
    virtual void drive(){}
    //包含一个隐含成员变量:虚函数表指针,该变量大小与操作系统位数有关
    //32位占4个字节,64位占8个字节
}    
#include<iostream>

using namespace std;

class Base{
public:
    virtual void Func1(){
        cout << "Base::Func1()" << endl;
    }
    virtual void Func2(){
        cout << "Base::Func2()" << endl;
    }
    void Func3(){
        cout << "Base::Func3()" << endl;
    }
private:
    int _b = 1;
};

class Derive : public Base{
public:
    virtual void Func1(){
        cout << "Derive::Func1()" << endl;
    }
private:
    int _d = 2;
};

void test(){
    Base b;
    Derive d;
}    

多态的实现依赖于虚函数表,如下图在这里插入图片描述
图中变量b和d中各包含一个_vfptr虚表指针,该指针指向一个虚表,虚表中存放各自的虚函数指针;
如果子类中有对父类重写的虚函数,则子类的虚表中对应位置使用子类虚函数指针进行覆盖;
若没有对父类的任何虚函数进行重写,则与父类的虚表相同;
虚函数指针在虚表中的存放位置和其声明或定义顺序是一致的,子类新定义的虚函数,按顺序放在虚表后面,虚表一般以nullptr结尾

总结
多态原理
如果访问的是虚函数,则通过指针/引用直到实际指向的实体,获取实体中的虚表指针,通过虚表指针访问虚表,在虚表中找到需要执行的虚函数的指针,再通过虚函数指针找到执行具体的函数行为

继承下的虚表
单继承虚表:
1.子类继承父类虚表
2.用重写的虚函数指针覆盖父类对应的虚函数指针
3.子类新定义的虚函数,其指针按照声明或者定义的顺序存入虚表的尾部

多继承虚表
1.虚表个数:等同于直接父类的个数
2.子类继承所有父类的虚表
3.用重写的虚函数指针覆盖父类中对应的虚函数指针
4.子类新定义的虚函数,其指针按照声明或者定义的顺序存入第一个直接父类的虚表的尾部

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值