多重继承的问题三: 多重继承可能产生多个虚函数表(BaseA和BaseB存在虚函数,有虚函数表,Derived将继承两个虚函数表) 编程实验:多重继承问题三
#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;
cout << "sizeof(d) = " << sizeof(d) << endl;
return 0;
}
因为Derived继承了两个虚函数表,Derived内部有两个虚函数表指针,因此创建对象的时候这两个成员会指向不同的虚函数表,两个指针16个字节
#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* 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 <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* paa = (BaseB*)pa;
BaseB* pbb = dynamic_cast<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();
cout << "pa = " << pa << endl;
cout << "pb = " << pb << endl;
cout << "paa = " << paa << endl;
cout << "pbb = " << pbb << endl;
return 0;
}
正确的使用多重继承 工程开发中的“多重继承”方式: 单继承某个类+实现(多个)接口 实验编程:正确的多继承方式
#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 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 :" <<p->equal(dynamic_cast<Base*>(pInt1)) << endl;
cout << "pInt2 == p :" <<p->equal(dynamic_cast<Base*>(pInt2)) << endl;
return 0;
}
一些有用的工程建议: (1)先继承自一个父类,然后实现多个接口 (2)父类中提供equal()成员函数 (3)equal()成员函数用于判断指针是否指向当前对象 (4)与多重继承相关的强制类型转换用dynamic_cast完成
小结: (1)多继承中可能出现多个虚函数表指针 (2)工程开发中采用单继承多接口的方式使用多继承 (3)父类提供成员函数用于判断指针是否指向当前对象
|