c++的多重继承

向右看齐 2022-07-15 19:46 318阅读 0赞

一、前言
每个类只继承一个父辈,在现实世界中事情通常是这样的,但是有一些类却代表两个类的合成。例如两用沙发,它是一张床,也是一个沙发。

二、示例代码,用作下面提出问题使用

  1. #include<iostream>
  2. using namespace std;
  3. class Bed
  4. {
  5. protected:
  6. int weight;
  7. public:
  8. Bed() :weight(0) {}
  9. void setWeight(int i) { weight = i; }
  10. void sleep()
  11. {
  12. cout << "Sleeping....." << endl;
  13. }
  14. };
  15. class Sofa
  16. {
  17. protected:
  18. int weight;
  19. public:
  20. Sofa() :weight(0) {}
  21. void setWeight(int i) { weight = i; }
  22. void watchTV()
  23. {
  24. cout << "Watch TV ..." << endl;
  25. }
  26. };
  27. class Bed_And_Sofa :public Bed, public Sofa
  28. {
  29. public:
  30. Bed_And_Sofa() {}
  31. void Foldout()
  32. {
  33. cout << "Fold Out.." << endl;
  34. }
  35. };
  36. int main()
  37. {
  38. Bed_And_Sofa a;
  39. a.watchTV();
  40. a.sleep();
  41. a.Foldout();
  42. cin.get();
  43. return 0;
  44. }

三、继承的模糊性
我们从示例代码中,可以发现他们共用的变量是weight,这样我们就不知道Bed_And_Sofa到底是继承哪一个,或者是两个都继承,那么你在使用的时候,使用哪个了?这样会造成weight的引用变的模糊。例如如下代码块:

  1. //为了修改weight的值,只有在主函数中输入如下代码,确定修改那个基类的weight
  2. int main()
  3. {
  4. Bed_And_Sofa a;
  5. a.Sofa::setWeight(20);
  6. }

如上的方式是可以解决,多继承带来的模糊性问题,但是这也增加了程序员的压力。

四、虚拟继承
从意义上来分析,我们刚才提出的两个例子,并没有什么现实生活的意义。但是我们都知道家具都是有重量的。所以我们把示例代码重新编写:

  1. #include<iostream>
  2. using namespace std;
  3. class Furniture
  4. {
  5. public :
  6. Furniture() {}
  7. void setWeight(int i)
  8. {
  9. weight = i;
  10. }
  11. int getWeight()
  12. {
  13. return weight;
  14. }
  15. protected:
  16. int weight;
  17. };
  18. class Bed:public Furniture
  19. {
  20. protected:
  21. int weight;
  22. public:
  23. Bed() :weight(0) {}
  24. void sleep()
  25. {
  26. cout << "Sleeping....." << endl;
  27. }
  28. };
  29. class Sofa:public Furniture
  30. {
  31. protected:
  32. int weight;
  33. public:
  34. Sofa() :weight(0) {}
  35. void watchTV()
  36. {
  37. cout << "Watch TV ..." << endl;
  38. }
  39. };
  40. class Bed_And_Sofa :public Bed, public Sofa
  41. {
  42. public:
  43. Bed_And_Sofa() {}
  44. void Foldout()
  45. {
  46. cout << "Fold Out.." << endl;
  47. }
  48. };
  49. int main()
  50. {
  51. Bed_And_Sofa a;
  52. a.setWeight(10); //程序编译不通过,因为这里的Furniture是一个不确定的值,我们不知道给f返回Bed继承的还是Sofa继承的。
  53. Furniture * f;
  54. f = (Furniture *)&a; //程序编译不通过,因为这里的Furniture是一个不确定的值,我们不知道给f返回Bed继承的还是Sofa继承的。
  55. cin.get();
  56. return 0;
  57. }

对于上述的问题,我们发现Bed_And_Sofa继承了两个Furniture类,出现了模糊继承的。所以为了解决这个问题,我们提出了虚拟继承。修改上述代码:

  1. #include<iostream>
  2. using namespace std;
  3. class Furniture
  4. {
  5. public :
  6. Furniture() {}
  7. void setWeight(int i)
  8. {
  9. weight = i;
  10. }
  11. int getWeight()
  12. {
  13. return weight;
  14. }
  15. protected:
  16. int weight;
  17. };
  18. class Bed:virtual public Furniture //虚拟继承
  19. {
  20. protected:
  21. int weight;
  22. public:
  23. Bed() :weight(0) {}
  24. void sleep()
  25. {
  26. cout << "Sleeping....." << endl;
  27. }
  28. };
  29. class Sofa :virtual public Furniture //虚拟继承
  30. {
  31. protected:
  32. int weight;
  33. public:
  34. Sofa() :weight(0) {}
  35. void watchTV()
  36. {
  37. cout << "Watch TV ..." << endl;
  38. }
  39. };
  40. class Bed_And_Sofa :public Bed, public Sofa
  41. {
  42. public:
  43. Bed_And_Sofa() {}
  44. void Foldout()
  45. {
  46. cout << "Fold Out.." << endl;
  47. }
  48. };
  49. int main()
  50. {
  51. Bed_And_Sofa a;
  52. a.setWeight(10);
  53. Furniture * f;
  54. f = (Furniture *)&a;
  55. cout << f->getWeight() << endl;
  56. cin.get();
  57. return 0;
  58. }

修改后的程序可以正常的执行,到底虚拟继承做了声明可以让程序正常执行了,下面我们给出Bed_And_Sofa的内存布局,你就明白了
这里写图片描述
所以virtual只是告诉系统,如果之前没有别人继承Furniture的话,那么就在加入一个Furniture拷贝,否则就用之前拷贝的那个。

五、多继承的构造顺序
(1)任何虚拟基类构造函数按照继承顺序构造
(2)任何非虚拟基类构造函数按照继承顺序构造
(3)任何成员对象的构造函数按照他们 的声明方式构造
(4)类自己的构造函数。

发表评论

表情:
评论列表 (有 0 条评论,318人围观)

还没有评论,来说两句吧...

相关阅读

    相关 c++多重继承

    一、前言 每个类只继承一个父辈,在现实世界中事情通常是这样的,但是有一些类却代表两个类的合成。例如两用沙发,它是一张床,也是一个沙发。 二、示例代码,用作下面提出问题使用