上一篇文章我们简单介绍了一下多继承的语法,但是我们遇到了一个问题,那就是如果多个父类具有相同名称的成员变量或成员方法,子类在调用的时候就会出现二义性问题,子类不知道选择哪一个父类的变量或方法,我们称之为三角问题。如下所示:
所以在编译的时候程序就无法通过了。其实解决这个问题有很多办法,先说一个最简单的办法就是使用域运算符,直接使用某个父类的成员函数或变量。如下所示:
代码语言:javascript复制#include
using namespace std;
class Bed
{
public:
void sleep()
{
cout << “Bed Sleep ~~” << endl;
}
protected:
int data;
};
class Sofa
{
public:
void sit()
{
cout << “Sofa sit ~~” << endl;
}
protected:
int data;
};
// 继承多个父类
class Derive : public Bed, public Sofa
{
public:
Derive()
:Bed(), Sofa() {}
void display()
{
// 使用作用域运算符,直接指定调用某个父类的成员
cout << Bed::data << endl;
cout << Sofa::data << endl;
}
};
int main(int argc, char* argv[])
{
Derive SofaBed;
SofaBed.sleep();
SofaBed.sit();
SofaBed.display();
return 0;
}
这是一种解决办法,当然,本文介绍的绝不止这些。在设计类的过程中,如果多个父类出现了同名的公有成员变量或方法,并且方法所执行的认为是一模一样的情况下,这证明我们设计的类是有问题的,应该保证实现同一功能的方法只有一个。那在上面的案例中我们需要抽象出一个基类,这个基类将Sofa和Bed两个类的公有同名变量或成员存放到基类中,然后让 Sofa 和 Bed 使用虚继承的方式,继承这个基类,这时,子类再多继承 Sofa 和 Bed 类的时候,就不会出现二义性问题了。其中 虚继承 起到了重要的作用,他让基类派生的两个类只保留了一份共有公共成员,这种情况,我们称之为钻石问题。
代码语言:javascript复制#include
using namespace std;
class M
{
public:
int data;
};
// 虚继承 M 类
class Bed : virtual public M
{
public:
void sleep()
{
cout << “Bed Sleep ~~” << endl;
}
};
// 虚继承 M 类
class Sofa : virtual public M
{
public:
void sit()
{
cout << “Sofa sit ~~” << endl;
}
};
// 继承多个父类
class Derive : public Bed, public Sofa
{
public:
Derive()
:Bed(), Sofa() {}
void display()
{
// 无需再担心二义性问题
cout << data << endl;
}
};
int main(int argc, char* argv[])
{
Derive SofaBed;
SofaBed.sleep();
SofaBed.sit();
SofaBed.display();
return 0;
}