日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多重继承、虚继承与虚基类

發布時間:2025/3/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多重继承、虚继承与虚基类 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、多重繼承

單重繼承——一個派生類最多只能有一個基類
多重繼承——一個派生類可以有多個基類

class 類名: 繼承方式 基類1,繼承方式 基類2,…. {….};

派生類同時繼承多個基類的成員,更好的軟件重用
可能會有大量的二義性,多個基類中可能包含同名變量或函數

多重繼承中解決訪問歧義的方法:

基類名::數據成員名(或成員函數(參數表))

明確指明要訪問定義于哪個基類中的成員

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
? #include?<iostream>
using?namespace?std;

class?Bed
{
public:
????Bed(int?weight)?:?weight_(weight)
????{

????}
????void?Sleep()
????{
????????cout?<<?"Sleep?..."?<<?endl;
????}
????int?weight_;
};

class?Sofa
{
public:
????Sofa(int?weight)?:?weight_(weight)
????{

????}
????void?WatchTV()
????{
????????cout?<<?"Watch?TV?..."?<<?endl;
????}
????int?weight_;
};

class?SofaBed?:?public?Bed,?public?Sofa
{
public:
????SofaBed()?:?Bed(0),?Sofa(0)
????{
????????FoldIn();
????}
????void?FoldOut()
????{
????????cout?<<?"FoldOut?..."?<<?endl;
????}
????void?FoldIn()
????{
????????cout?<<?"FoldIn?..."?<<?endl;
????}
};

int?main(void)
{
????SofaBed?sofaBed;
????//sofaBed.weight_?=?10;?error
????//sofaBed.weight_?=?20;?error

????sofaBed.Bed::weight_?=?10;
????sofaBed.Sofa::weight_?=?20;

????sofaBed.WatchTV();
????sofaBed.FoldOut();
????sofaBed.Sleep();

????return?0;
}

不能直接寫?sofaBed.weight_ = 10; 因為sofaBed 繼承了Sofa 和 Bed ,實際上有weigh_的兩份拷貝,這樣指向不明。只能通過

sofaBed.Bed::weight_ = 10; 訪問,但實際上一個sofaBed理應只有一個weight_,下面通過虛基類和虛繼承可以解決這個問題。


二、虛繼承與虛基類

當派生類從多個基類派生,而這些基類又從同一個基類派生,則在訪問此共同基類中的成員時,將產生二義性,可以采用虛基類來解決。

虛基類的引入

用于有共同基類的場合

聲明

以virtual修飾說明基類 例:class B1:virtual public BB

作用

主要用來解決多繼承時可能發生的對同一基類繼承多次而產生的二義性問題.

為最遠的派生類提供唯一的基類成員,而不重復產生多次拷貝

?

C++ Code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
? #include?<iostream>
using?namespace?std;

class?Furniture
{
public:
????Furniture(int?weight)?:?weight_(weight)
????{
????????cout?<<?"Furniture?..."?<<?endl;
????}
????~Furniture()
????{
????????cout?<<?"~Furniture?..."?<<?endl;
????}
????int?weight_;
};

class?Bed?:?virtual?public?Furniture
{
public:
????Bed(int?weight)?:?Furniture(weight)
????{
????????cout?<<?"Bed?..."?<<?endl;
????}
????~Bed()
????{
????????cout?<<?"~Bed?..."?<<?endl;
????}
????void?Sleep()
????{
????????cout?<<?"Sleep?..."?<<?endl;
????}

};

class?Sofa?:?virtual?public?Furniture
{
public:
????Sofa(int?weight)?:?Furniture(weight)
????{
????????cout?<<?"Sofa?..."?<<?endl;
????}
????~Sofa()
????{
????????cout?<<?"~Sofa?..."?<<?endl;
????}
????void?WatchTV()
????{
????????cout?<<?"Watch?TV?..."?<<?endl;
????}
};

class?SofaBed?:?public?Bed,?public?Sofa
{
public:
????SofaBed(int?weight)?:?Bed(weight),?Sofa(weight),?Furniture(weight)
????{
????????cout?<<?"SofaBed?..."?<<?endl;
????????FoldIn();
????}
????~SofaBed()
????{
????????cout?<<?"~SofaBed?..."?<<?endl;
????}
????void?FoldOut()
????{
????????cout?<<?"FoldOut?..."?<<?endl;
????}
????void?FoldIn()
????{
????????cout?<<?"FoldIn?..."?<<?endl;
????}
};

int?main(void)
{
????SofaBed?sofaBed(5);
????sofaBed.weight_?=?10;


????sofaBed.WatchTV();
????sofaBed.FoldOut();
????sofaBed.Sleep();

????return?0;
}



此時只有一份weigh_,不存在訪問歧義的問題。

從輸出可以總結出:

1、虛基類的成員是由最遠派生類的構造函數通過調用虛基類的構造函數進行初始化的。
2、在整個繼承結構中,直接或間接繼承虛基類的所有派生類,都必須在構造函數的成員初始化表中給出對虛基類的構造函數的調用。如果未列出,則表示調用該虛基類的默認構造函數。
3、在建立對象時,只有最遠派生類的構造函數調用虛基類的構造函數,該派生類的其他基類對虛基類構造函數的調用被忽略。

?

參考:

C++ primer 第四版
Effective C++ 3rd
C++編程規范

總結

以上是生活随笔為你收集整理的多重继承、虚继承与虚基类的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。