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

来源:互联网 发布:java 方法名 编辑:程序博客网 时间:2024/06/14 00:14

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) = 8Using pa to call funcA()...BaseA::funcA()Using pb to call funcB()...BaseB::funcB()Using pbc to call funcB()...BaseB::funcB()pa = 0x7ffed5f93090pb = 0x7ffed5f93098pbe = 0x7ffed5f93090pbc = 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() = 100p->getI() = 40pInt1 == p : 1pInt2 == p : 1

4、

这里写图片描述

5、小结

这里写图片描述