多重继承的问题三:
多重继承可能产生多个虚函数表(baseA和baseB存在虚函数,有虚函数表,Derived将继承两个虚函数表)
编程实验:多重继承问题三
#include#include 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; cout << "sizeof(d) = " << sizeof(d) << endl; return 0; }
因为Derived继承了两个虚函数表,Derived内部有两个虚函数表指针,因此创建对象的时候这两个成员会指向不同的虚函数表,两个指针16个字节
#include#include 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* pbb = (baseB*)pa; cout << "sizeof(d) = " << sizeof(d) << endl; cout << "using pa to call funcA()..." << endl; pa->funcA(); cout << "using pb to call funcB()..." << endl; pb->funcB(); cout << "using pbb to call funcB()..." << endl; pbb->funcB(); return 0; }
竟然调用了funcA,不是funcB。
解决方案:需要进行强制类型转换时,C++中推荐使用新式类型转换关键字!!
#include#include 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* paa = (baseB*)pa; baseB* pbb = dynamic_cast (pa); //error cout << "sizeof(d) = " << sizeof(d) << endl; cout << "using pa to call funcA()..." << endl; pa->funcA(); cout << "using pb to call funcB()..." << endl; pb->funcB(); cout << "using pbb to call funcB()..." << endl; pbb->funcB(); cout << "pa = " << pa << endl; cout << "pb = " << pb << endl; cout << "paa = " << paa << endl; cout << "pbb = " << pbb << endl; return 0; }
正确的使用多重继承
工程开发中的“多重继承”方式:
单继承某个类+实现(多个)接口
实验编程:正确的多继承方式
#include#include 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 Detived : public base, public Interface1, public Interface2 { public: Detived(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() { Detived d(100); Detived* p = &d; Interface1* pInt1 = &d; Interface2* pInt2 = &d; cout << "p->getI() = " << p->getI() << endl; pInt1->add(10); pInt2->divide(11); pInt1->minus(5); pInt2->multiply(8); cout << "p->getI() = " << p->getI() << endl; cout << "pInt1 == p :" < equal(dynamic_cast (pInt1)) << endl; cout << "pInt2 == p :" < equal(dynamic_cast (pInt2)) << endl; return 0; }
一些有用的工程建议:
(1)先继承自一个父类,然后实现多个接口
(2)父类中提供equal()成员函数
(3)equal()成员函数用于判断指针是否指向当前对象
(4)与多重继承相关的强制类型转换用dynamic_cast完成
小结:
(1)多继承中可能出现多个虚函数表指针
(2)工程开发中采用单继承多接口的方式使用多继承
(3)父类提供成员函数用于判断指针是否指向当前对象



