54-多重继承(下)单继承多接口

1、多重继承问题三

这里写图片描述
Derived继承BaseA和BaseB,如果AB中都含有1个虚函数,那么Derived就会叠加产生2个虚函数表指针指向这两个虚函数表

#include <iostream>
#include <string>

using namespace std;

class BaseA
{
public:
    virtual void funcA()
    {
        cout << "BaseA::funcA()" << endl;
    }
};

class BaseB
{
public:
    virtual void funcB()
    {
        cout << "BaseB::funcB()" << endl;
    }
};

class Derived : public BaseA, public BaseB
{

};

int main()
{
    Derived d;
    BaseA* pa = &d;
    BaseB* pb = &d;
    BaseB* pbe = (BaseB*)pa;    // oops!!  这种强制类型转化有问题
    BaseB* pbc = dynamic_cast<BaseB*>(pa);
    //在与继承,与虚函数相关的强制类型转换时,使用dynamic_cast关键字
    //dynamic_cast对指针进行了修正,使pbc指向pb的位置


    //Derived没有任何成员变量,验证虚函数表指针存在,
    cout << "sizeof(d) = " << sizeof(d) << endl; //8字节


    cout << "Using pa to call funcA()..." << endl;

    pa->funcA();//符合预期,父类指针指向子类,调用子类的成员函数

    cout << "Using pb to call funcB()..." << endl;

    pb->funcB();

    cout << "Using pbc to call funcB()..." << endl;

    pbc->funcB();
    //将pa指针指向的d对象,通过BaseB*转换为指向pb,
    //然后调用pbe->funcB()函数,想要输出"BaseB::funcB()"
    //其实BaseB* pbe = (BaseB*)pa;后,pbe指向的还是pa!!!
    //所以调用的是"BaseA::funcA()",这种强制转换造成了内存未按预期对齐
    cout << endl;

    cout << "pa = " << pa << endl;
    cout << "pb = " << pb << endl;
    cout << "pbe = " << pbe << endl;
    cout << "pbc = " << pbc << endl;

    return 0;
}
sizeof(d) = 8
Using pa to call funcA()...
BaseA::funcA()
Using pb to call funcB()...
BaseB::funcB()
Using pbc to call funcB()...
BaseB::funcB()

pa = 0x7ffed5f93090
pb = 0x7ffed5f93098
pbe = 0x7ffed5f93090
pbc = 0x7ffed5f93098
2、解决方案

这里写图片描述
在d对象里面存在两个指向虚函数表的指针,这是由于继承而来的。
先用pa指向d对象,再用pb指向d对象,pa和pb指向的位置不一样
接下来通过pa进行强制类型转换,将转换的结果给pbb指针,此时pbb所指向的位置为pa的位置,不是pb的位置。

虚函数调用的过程:
首先先获取pa的地址通过地址找到虚函数表指针vptr1,进而通过
虚函数表指针去找虚函数表中的函数地址,找到funcA的函数地址
同理pb一样;
pbb也是找到vptr1的虚函数表,但是里面不存在funcB的函数,只有函数funcA的函数,最终调用funcA函数,
所以BaseB* pbb = (BaseB*)pa; 这个强制类型转换有问题
所以要使用BaseB* pbb =dynamic_cast

3、正确的使用多重继承

这里写图片描述

#include <iostream>
#include <string>

using namespace std;

class Base
{
protected:
    int mi;
public:
    Base(int i)
    {
        mi = i;
    }
    int getI()
    {
        return mi;
    }
    bool equal(Base* obj)//判断参数的指针指向的是否为当前对象

    {
        return (this == obj);
    }
};

class Interface1
{
public:
    virtual void add(int i) = 0;
    //纯虚函数为抽象类,该类只能继承不能实例化
    virtual void minus(int i) = 0;
};

class Interface2
{
public:
    virtual void multiply(int i) = 0;
    virtual void divide(int i) = 0;
};

class Derived : public Base, public Interface1, public Interface2
{
public:
    Derived(int i) : Base(i)
    {
    }
    void add(int i)
    {
        mi += i;
    }
    void minus(int i)
    {
        mi -= i;
    }
    void multiply(int i)
    {
        mi *= i;
    }
    void divide(int i)
    {
        if( i != 0 )
        {
            mi /= i;
        }
    }
};

int main()
{
    Derived d(100);
    Derived* p = &d;
    Interface1* pInt1 = &d;
    Interface2* pInt2 = &d;

    cout << "p->getI() = " << p->getI() << endl;    // 100

    pInt1->add(10);
    pInt2->divide(11);
    pInt1->minus(5);
    pInt2->multiply(8);

    cout << "p->getI() = " << p->getI() << endl;    // 40

    cout << endl;

    cout << "pInt1 == p : " << p->equal(dynamic_cast<Base*>(pInt1)) << endl;
    cout << "pInt2 == p : " << p->equal(dynamic_cast<Base*>(pInt2)) << endl;
    //p->equal(pInt1)这样的话会造成类型不匹配,必须使用dynamic_cast进行强制类型转化
    //hellp.cpp:84:48: error: no matching function for call to ‘Derived::equal(Interface1*&)’
    // cout << "pInt1 == p : " << p->equal((pInt1)) << endl;

    return 0;
}
p->getI() = 100
p->getI() = 40

pInt1 == p : 1
pInt2 == p : 1
4、

这里写图片描述

5、小结

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值