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