1.菱形的相關問題
1.什麼是菱形繼承?
菱形繼承是C++繼承中的多繼承出現的問題。
2.菱形繼承帶來什麼問題,如何解決?
帶來數據二義性,和數據冗餘問題。
二義性可以通過作用域限定符,限定所操作的數據對象。
數據冗餘問題,需要通過虛擬繼承來解決。
圖解:
3.什麼是組合,什麼是繼承,適用情況有哪些?
組合和繼承都是面向對象編程代碼複用的方式。
組合是解決has-a的問題,(車有發動機)。
優點:封裝性沒有被破壞,類與類的耦合度低。
缺點:調用的時候是通過對象訪問調用接口,不能直接使用接口。
繼承是解決Is-a的問題,(人,學生,老師)
優點:子類直接繼承父類的接口,創建對象時不用創建父類對象。
缺點:父類與子類的耦合度增加,破壞了封裝性,不利於程序的維護。
2.代碼展示
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class per
{
public:
int _num1;
};
class stu:virtual public per
{
public:
int _num2;
};
class teach :virtual public per
{
public:
int _num3;
};
class ass : public teach, public stu
{
public:
int _num4;
};
void test6()
{
per p;
p._num1 = 1;
cout << p._num1 << endl;
stu s;
s._num1 = 21, s._num2 = 22;
cout << s._num1 <<" "<< s._num2 << endl;
teach t;
t._num1 = 31, t._num3 = 33;
cout << t._num1 << " " << t._num3 << endl;
ass a;
a._num1 = 41, a._num2 = 42, a._num3 = 43, a._num4 = 44;
a.stu::_num1 = 411, a.teach::_num1 = 4111;
cout <<a._num1 << " " << a._num2 << " " << a._num3 << " " << a._num4 << endl;
cout << t._num1 << " " << t._num3 << endl;
//printf("%p", *(int*)&a);
}
int main()
{
test6();
system("pause");
return 0;
}
3.結果展示
4.結果分析
通過查看地址的方式,我發現虛擬繼承virtual繼承,子類繼承父類的時候,增加了一個虛基表指針,指向虛基表,虛基表的位置存儲的是00000000,下一個位置存儲的是偏移量,即虛基表指針到數據的位置,結尾一般是00000000,而且它們共用一個虛基表。重複的冗餘的數據,放在數據的末尾。
虛基表在內存中放在數據段,下面通過查看地址發現兩個位置非常近。