C++多态

一.多态

        多态通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会 产生出不同的状态

1.多态的条件

1.必须通过基类的指针或者引用调用虚函数

2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

执行基类调基类,指向派生类调派生类的虚函数,比如

2.虚函数重写

        派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的 返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。比如上面的A类与B类里面的fun函数,函数相同,参数相同,返回值相同,并使用virtual关键字,构成重写

特例:

1.协变

虚函数可以返回值不相同,但必须是父子类的指针或引用 比如

但反过来就不行

2.析构函数

        如果我们用基类的指针指向派生类,再delete这个指针,但这只会调用派生类里基类部分的析构函数,属于派生类的部分没有释放,会造成内存泄漏,所以这个地方我们需要多态解决

        析构函数被做了一个特殊处理,析构函数的名称会被统一为destructor,加上virtual关键字即可实现多态调用

实现多态调用                                                     没有多态调用

3.抽象类

        在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口 类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生 类才能实例化出对象。纯虚函数规范了派生类必须重写

4.重载,重写,隐藏

重载:在同一作用域里,函数名相同,参数不相同构成重载

重写:在基类和派生类里,函数名相同,参数相同,返回值相同(协变除外),俩函数是虚函数构成重写

隐藏:在基类和派生类里,只要函数名相同就构成隐藏

二.多态的原理

1.虚函数表

比如这个实现多态,在B类里面,会多一个指针

这是一个函数指针数组,我们称对象里的这个指针叫虚函数表指针,存放虚函数指针,虚表存在常量区

虚表在编译时生成,在对象构造时把地址赋值给对象里面的虚表指针,

2.多态的原理

1.单继承的虚表

        我们来看这个虚函数表,a对象里的虚函数表有A类的fun,A类的func,b对象里面的虚函数表有A类的func,有B类重写的fun,我们打印一下虚表(因为在VS中,虚表是以空为结尾,可以利用这个打印)

2.多基础的虚表

与单继承不同的是,多继承会有多份虚表,自己新增的虚函数一般会放在第一个虚表里面

3.菱形虚拟继承的虚表

class A
{
public:
    virtual void fun()
    {
        cout << "这是A类的fun()" << endl;
    }
    virtual void func()
    {
        cout << "这是A类的func()" << endl;
    }
};
class B :virtual public A
{
public:
    virtual void fun()
    {
        cout << "这是B类的fun()" << endl;
    }
    virtual void f()
    {
        cout << "这是B类的f()" << endl;
    }
};
class C :virtual public A
{
public:
    virtual void fun()
    {
        cout << "这是C类的fun()" << endl;
    }
};
class D :public C, public B
{
public:
    virtual void fun()
    {
        cout << "这是D类的fun()" << endl;
    }
    int a=0;
};

        菱形虚拟继承中只会存在一张虚表,如果这是菱形继承,那么就会存在B类的虚表,C类的虚表,现在只剩下一张虚表,所以就会存在一种问题,那就是重写的不明确,比如上面的B,C类都重写了fun函数,然后D类就会出现重写不明确的问题,解决方法是D类重写fun,或者B,C,类一个不重写fun函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值