標籤:沒有 成員函數 using 執行個體 int 預設建構函式 理解 虛基類 產生
?在開發衍生類別的過程中,按基類成員在基類中的存取控制,操作基類成員。
?
C++提供了下面幾種代碼重用的手段:
1. 繼承(公有繼承(is-a)、私人繼承和保護繼承(has-a));
2. 包含/層次化/組合(has-a);
3. 多重繼承
4. 類模板
繼承了實現就是繼承了資料成員,繼承了介面就是繼承了成員函數。
介面(衍生類別對象可以使用基類的方法)和實現(衍生類別Object Storage Service了基類的資料成員,實現即為可以對資料成員進行操作(通過成員函數))
使用公有繼承時,類可以繼承介面,可能還有實現(基類的純虛函數提供介面,但不提供實現)。獲得介面是is-a關係的組成部分。而使用組合,類可以獲得實現,但不能獲得介面。不獲得介面是has-a關係的組成部分。
雖然has-a關係的繼承沒有繼承基類的介面,但可以在衍生類別的成員函數內部使用基類名和範圍運算子來訪問基類方法。
私人繼承
使用私人繼承,基類的私人成員、保護成員都將成為衍生類別的私人成員。這意味著,基類方法不會成為衍生類別對象公有介面的一部分,但可以在衍生類別的成員函數中使用它們。
‘包含‘ 將對象作為一個命名的成員對象添加到類中;而私人繼承將對象作為一個未被命名的繼承對象添加到類中。
私人繼承的技術:
1. 初始化基類組件
建構函式使用成員初始化列表,使用類名而不是成員名來表示建構函式。
每一個繼承的基類只對應一個成員對象。
2. 訪問基類的方法
可以通過類名和範圍解析運算子來調用基類的方法。
3. 訪問基類對象
通過私人繼承的衍生類別如何訪問基類對象?答案是使用強制類型轉換。
4. 訪問基類的友元函數
同樣通過強制類型轉換
當需要簡曆has-a關係時,使用基類還是私人繼承
包含的優點:1. 易於理解;2. 繼承會引起許多問題(多重繼承時);3. 包含能夠包括多個同類子物件。
繼承的優點:1. 在衍生類別中可以使用基類的保護成員,而包含不能訪問對象成員的保護成員;2. 當需要重定義虛函數時。
保護繼承
保護繼承是私人繼承的變體,使用保護繼承時,基類的公有和保護成員都將成為衍生類別的保護成員。
私人繼承和保護繼承之間的主要區別在第三代類中體現。私人繼承的第三代類不能使用基類的方法(因為私人繼承的基類的公有和保護成員將會成為第二代類的私人成員),而保護繼承可以。
隱式向上類型轉換意味著無需進行顯式類型轉換,就可以將基類指標或引用指向衍生類別。
私人繼承不能隱式向上類型轉換,公有繼承可以,保護繼承在衍生類別中可以(?)。
使用using重新定義存取權限
使用保護或私人派生時,想讓基類的方法在衍生類別外面可用,可將函數調用封裝在另一個函數調用中,即使用一個using聲明來指出衍生類別可以使用特定的基類成員。
class Student : std::valarray<double>{ ......public: using std::valarray<double>::min; ...... }
多重繼承(MI)
MI主要給程式員帶來兩個問題:
1. 從兩個不同的基類繼承同名方法(基類之間有同名的方法)(在衍生類別中使用類限定符來區分它們);
2. 從多個相關基類那裡繼承同一個類的多個執行個體(有多個基類繼承於一個祖先時,將會在對象中產生一個類的多個執行個體)。
解決問題2.
多重派生對象將會產生各個基類對象,及基類的各級祖先類對象。若有多個基類繼承與一個祖先,將會產生這個祖先的多個執行個體,產生二義問題。
C++引入了虛基類,在類聲明中使用關鍵字virtual,使被限定的類成為虛基類。虛基類使多重派生對象只有一個(同時來自多個基類的)祖先類副本。
1 //祖先類(在Singer和Waiter類聲明中被限定為虛基類) 2 class Worker { ...... }; 3 4 //基類Singer 5 class Singer : virtual public Worker 6 { ...... }; 7 //基類Waiter 8 class Waiter: virtual public Worker 9 { ...... };10 11 //多重衍生類別SingerWaiter 12 class SingerWaiter: public Worker, public Waiter13 { ...... };
引入虛基類時,必須修改代碼:(以下的祖先類表示多個類共同的(虛)基類)
引入虛基類前,在建構函式中用列表初始化基類成員對象時,一個祖先類對象將通過多個途徑傳遞到多個基類建構函式。
為避免這個問題C++在祖先類是虛的時,禁止資訊通過中間類自動傳遞給祖先類,預設調用祖先類的預設建構函式。
也可以顯式的在成員列表初始化中調用祖先類的建構函式。
問題1.
如果從不同基類中繼承了兩個或多個同名成員,使用該成員名時,如果沒有用類名進行限定將導致二義性。
但如果使用的是虛基類,這樣做不一定會導致二義性。如果某個名稱優先於其它所有名稱則使用它,即便沒有用類名限定,也不會導致二義性。
如何判斷名稱優先?
衍生類別中的名稱優先於直接或間接祖先類中相同的名稱。
虛二義性規則與訪問規則無關:
即使同名函數是私人的,也不影響其優先順序。
MI的複雜性主要是由衍生類別通過多條途徑繼承同一個基類引起的。
。。。待續
模板類valarray簡介
valarray類對象用於儲存數字,提供了豐富的算術支援。
valarray<double> v1; //空數組valarray<int> v2(8); //8個int元素的數組valarray<float> v3(10.1, 8); //8個float元素的數組,每個元素的值都為10.1int gpa[5] = {1, 2, 3, 4, 5};valarray<int> v4(gpa, 4); //v4被初始化為gpa的前4個元素
在C++11中,可以對valarray對象進行列表初始化。
常用方法:
size();
sum();
min();
max().
第十四章 C++中的代碼重用