c++的多重继承
一、前言
每个类只继承一个父辈,在现实世界中事情通常是这样的,但是有一些类却代表两个类的合成。例如两用沙发,它是一张床,也是一个沙发。
二、示例代码,用作下面提出问题使用
#include<iostream>
using namespace std;
class Bed
{
protected:
int weight;
public:
Bed() :weight(0) {}
void setWeight(int i) { weight = i; }
void sleep()
{
cout << "Sleeping....." << endl;
}
};
class Sofa
{
protected:
int weight;
public:
Sofa() :weight(0) {}
void setWeight(int i) { weight = i; }
void watchTV()
{
cout << "Watch TV ..." << endl;
}
};
class Bed_And_Sofa :public Bed, public Sofa
{
public:
Bed_And_Sofa() {}
void Foldout()
{
cout << "Fold Out.." << endl;
}
};
int main()
{
Bed_And_Sofa a;
a.watchTV();
a.sleep();
a.Foldout();
cin.get();
return 0;
}
三、继承的模糊性
我们从示例代码中,可以发现他们共用的变量是weight,这样我们就不知道Bed_And_Sofa到底是继承哪一个,或者是两个都继承,那么你在使用的时候,使用哪个了?这样会造成weight的引用变的模糊。例如如下代码块:
//为了修改weight的值,只有在主函数中输入如下代码,确定修改那个基类的weight
int main()
{
Bed_And_Sofa a;
a.Sofa::setWeight(20);
}
如上的方式是可以解决,多继承带来的模糊性问题,但是这也增加了程序员的压力。
四、虚拟继承
从意义上来分析,我们刚才提出的两个例子,并没有什么现实生活的意义。但是我们都知道家具都是有重量的。所以我们把示例代码重新编写:
#include<iostream>
using namespace std;
class Furniture
{
public :
Furniture() {}
void setWeight(int i)
{
weight = i;
}
int getWeight()
{
return weight;
}
protected:
int weight;
};
class Bed:public Furniture
{
protected:
int weight;
public:
Bed() :weight(0) {}
void sleep()
{
cout << "Sleeping....." << endl;
}
};
class Sofa:public Furniture
{
protected:
int weight;
public:
Sofa() :weight(0) {}
void watchTV()
{
cout << "Watch TV ..." << endl;
}
};
class Bed_And_Sofa :public Bed, public Sofa
{
public:
Bed_And_Sofa() {}
void Foldout()
{
cout << "Fold Out.." << endl;
}
};
int main()
{
Bed_And_Sofa a;
a.setWeight(10); //程序编译不通过,因为这里的Furniture是一个不确定的值,我们不知道给f返回Bed继承的还是Sofa继承的。
Furniture * f;
f = (Furniture *)&a; //程序编译不通过,因为这里的Furniture是一个不确定的值,我们不知道给f返回Bed继承的还是Sofa继承的。
cin.get();
return 0;
}
对于上述的问题,我们发现Bed_And_Sofa继承了两个Furniture类,出现了模糊继承的。所以为了解决这个问题,我们提出了虚拟继承。修改上述代码:
#include<iostream>
using namespace std;
class Furniture
{
public :
Furniture() {}
void setWeight(int i)
{
weight = i;
}
int getWeight()
{
return weight;
}
protected:
int weight;
};
class Bed:virtual public Furniture //虚拟继承
{
protected:
int weight;
public:
Bed() :weight(0) {}
void sleep()
{
cout << "Sleeping....." << endl;
}
};
class Sofa :virtual public Furniture //虚拟继承
{
protected:
int weight;
public:
Sofa() :weight(0) {}
void watchTV()
{
cout << "Watch TV ..." << endl;
}
};
class Bed_And_Sofa :public Bed, public Sofa
{
public:
Bed_And_Sofa() {}
void Foldout()
{
cout << "Fold Out.." << endl;
}
};
int main()
{
Bed_And_Sofa a;
a.setWeight(10);
Furniture * f;
f = (Furniture *)&a;
cout << f->getWeight() << endl;
cin.get();
return 0;
}
修改后的程序可以正常的执行,到底虚拟继承做了声明可以让程序正常执行了,下面我们给出Bed_And_Sofa的内存布局,你就明白了
所以virtual只是告诉系统,如果之前没有别人继承Furniture的话,那么就在加入一个Furniture拷贝,否则就用之前拷贝的那个。
五、多继承的构造顺序
(1)任何虚拟基类构造函数按照继承顺序构造
(2)任何非虚拟基类构造函数按照继承顺序构造
(3)任何成员对象的构造函数按照他们 的声明方式构造
(4)类自己的构造函数。
还没有评论,来说两句吧...