【C++】54.被遗弃的多重继承(下)

接着上一课分析 ......

 

多重继承的问题三

多重继承可能产生多个虚函数表

示例:

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
{
	
public:
	void func()
    {
        cout << "Derived::funcB()" << endl;
    }	
};


int main()
{
	Derived d;
	
	cout << "sizeof(d) = " << sizeof(d) << endl;  // 两个虚函数表指针
	
	BaseA *pa = &d;
	BaseB *pb = &d;
	
	pa->funcA();
	pb->funcB();
	
	cout << endl;
	
	BaseB *pbc = (BaseB*)pa;
	BaseB *pbd = dynamic_cast<BaseB*>(pa);
	
	cout << "Except funcB(), result: " ;
	pbc->funcB();
	
	cout << endl;
	
	cout << "Except funcB(), result: " ;
	pbd->funcB();
	
	
	cout << endl;
	
    cout << "pa = " << pa << endl;
    cout << "pb = " << pb << endl;
	cout << "pbc = " << pbc << endl;
    cout << "pbd = " << pbd << endl;
   
  
    return 0;
}

输出结果

sizeof(d) = 16      // 64位虚拟机
BaseA::funcA()
BaseB::funcB()

Except funcB(), result: BaseA::funcA()

Except funcB(), result: BaseB::funcB()

 pa = 0x7ffcb86e0cc0
pb = 0x7ffcb86e0cc8
pbc = 0x7ffcb86e0cc0
pbd = 0x7ffcb86e0cc8

在需要进行强制类型转换时, C++中推荐使用新式类型转换关键字

解决方法: dynamic_cast

Derived d;
BaseA *pa = &d;
BaseB *pb = &d;
BaseB *pbb = dynamic_cast<Base*>(pa);

扫描二维码关注公众号,回复: 8649616 查看本文章

实际开发中采用“多重继承”这种方案

单继承某个类 + 实现(多个)接口

示例:

#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;
    
    return 0;
}

工程有用建议

  • 先继承自一个父类,然后实现多个接口
  • 父类中提供 equal 成员函数
  • euqal() 成员函数用于判断指针是否指向当前对象
  • 与多重继承相关的强制类型转换使用 dynamic_cast 完成
  • 接口仅仅定义公有的接口函数而已

小结

  • 多继承中可能出现多个虚函数表指针
  • 与多继承相关的强制类型转换用 dynamic_cast 完成
  • 工程开发中采用"单继承多接口" 的方式使用多继承
  • 父类提供成员函数用于判断指针是否指向当前对象

发布了84 篇原创文章 · 获赞 0 · 访问量 722

猜你喜欢

转载自blog.csdn.net/zhabin0607/article/details/103917152