//多重继承的二义性以及解决方法
//学习目的:了解类的继承原理及多重继承二义性的解决方法。
/*
//本程序代码来源《MFC权威剖析》p68
*/
第一种多重继承的二义性
class Employee
{
public:
char Name[40];
bool Sex;
};
class Worker : public Employee
{
};
class Manager : public Employee
{
};
class Engineer : public Worker, public Manager
{
};
//Engineer的实例化对象内存中包含两个Employee子对象,分别属于Worker和Manager子对象,
//这样在该实例的内部就封装了两套员工个人档案,显然是错误的。
{
Engineer eng;
eng.Worker::Sex = true;
eng.Manager::Sex = false;//eng的性别即使男又是女
}
/解决办法
//在父类存在共同双亲的情况下,可以通过虚拟基类来解决。
//虚拟基类的作用是:如果在一个派生类的继承结构中,存在两个同样的虚拟基类,那么
//该类的实例化对象内存中只存在一个虚拟基类的子对象。
//事例
class Employee
{
public:
char Name[40];
bool Sex;
};
class Worker : public virtual Employee //Employee
{
};
class Manager : public virtual Employee //Employee
{
};
class Engineer : public Worker, public Manager
{
};
//这样的继承方式,虚拟基类的子对象不再包含在每个父类中,而是单独存在。
//父类对象中存在一个指向其虚拟父类子对象的一个指针,该指针被称为虚父类指针,
//由编译器生成。这样就保证了在多重继承时,子类实例中只存在一个虚拟基类的子对象。
//但同名的非虚拟基类的子对象没有被合并。
/第二种多重继承的二义性
class ParentA
{
public:
void fun() {printf("%d\n", m_Value); };
private:
int m_Value;
};
class ParentB
{
public:
void fun() {printf("%d\n", m_Value); };
private:
int m_Value;
};
class Son : public ParentA, public ParentB
{
};
///解决办法
//在父类没有共同双亲的情况下,一般在子类中将名字冲突的成员重新定义,
//以此解决二义性。
/使用虚拟基类需要注意的问题
//应用虚拟基类虽然解决了基类子对象重复问题,但还不能完全消除二义性的可能。
//如果两个直接父类同时定义了同名的函数,则还会产生二义性。