C++學習隨筆之十一:C++中的代碼重用

來源:互聯網
上載者:User

引言:C++的一個主要目的是代碼重用,提高效率,公有繼承是實現這個目的的一種機制。還有其他的機制,本部分主要介紹其他代碼重用方法,一種是包含、組合或層次化,另一種是私人或保護繼承,通常組合、私人繼承和保護繼承喲國語實現has-a關係,即新的對類將包含另一個類的對象。還有一種就是和函數模板對應的類模板。

1.包含對象成員的類:

包含對象的類就是這樣一種類:類中包含了這樣的一個類成員:本身是另一個類的對象。這種方法稱為包含、組合或層次化。

C++和約束:C++包含讓程式員能夠限制程式結構的特性——使用explicit防止單參數建構函式的隱式轉換,使用const限制方法修改資料等等。這樣做的根本原因是:在編譯階段出現錯誤要比在運行階段出現錯誤要好,要優。

初始化順序:當初始化列表包含多重專案時,這些項目被初始化的順序為它們被聲明的順序,而不是它們在初始化列表中的順序。例如:

Student(const char *str,const double *pd,int n):scores(pd,n),name(str){}

則name成員仍將首先初始化,因為在類定義中它首先被聲明。

介面和實現:使用公有繼承是,類可以繼承介面,可能還有實現(基類的純虛函數提供介面,但不提供實現)。獲得介面是is-a關係的組成部分。而是用組合,類可以獲得實現,但不能獲得介面。不繼承介面是has-a關係的組成部分。

2.私人繼承和保護繼承:

私人繼承:

私人繼承,也是實現has-a關係的一種途徑。使用私人繼承,基類的公有成員和保護成員都將成為衍生類別的私人成員。這就意味著基類方法將不會成為衍生類別對象公有介面的一部分,但可以在衍生類別的成員函數中使用它們。

介面問題:使用公有繼承,基類的公有方法將成為衍生類別的公有方法,。簡而言之,衍生類別將繼承基類的介面;這是is-a關係的一部分。使用私人繼承,基類的公有方法就成為衍生類別的私人方法,簡而言之,衍生類別不繼承基類的介面。這種不完全繼承是has-a的關係的一部分。

使用私人繼承類將繼承實現。

包含是將對象作為一個命名的成員對象添加到類中,而私人繼承將對象作為一個未被命名的繼承對象添加到類中。一般用術語子物件來表示通過繼承或包含添加的對象。

從上面可知,私人繼承的特性和包含(組合)相同,所以,私人繼承也可以用來實現has-a關係。

訪問基類的方法:使用包含時將使用對象名來調用方法,而是用私人繼承時將使用類名和範圍解析操作符::來調用方法

訪問基類對象:一般使用強制類型轉換。例如:Student類是string類派生而來的:

cosnt string & Student::Name()const

{

return (const string &) *this;

}

訪問基類的友元函數:用類名顯示地限定函數名不適合與友元函數,因為友元不是類成員,不過,可以通過顯式地轉換為基類來調用正確的函數。例如,對於下面的友元函數定義:

ostream & operator<<(ostream & os,Student & stu)

{

os <<"Scores for " <<(const string &) stu <<":\n";

...

}

如果pstu是一個Student對象,則下面的語句:

cout<<pstu;將調用上述函數,stu將是指向pstu的引用,而os將是指向cout的引用。下面的代碼:

os<<"Scores for " << (const string &) stu <<":\n"; 顯式地將stu轉換為string對象的引用,這與operator<<(ostream &,cosnt String &)函數匹配

引用stu不會自動轉換為sting引用。根本原因在於,在私人繼承中,在不進行顯式類型轉換的情況下,不能將指向衍生類別的引用或指標賦給基類應用或指標。

不過,即使這個例子使用的是公有繼承,也必須使用顯示類型轉換。原因之一是,如果不使用類型轉換,下面代碼將與友元函數原型匹配,從而導致遞迴調用:os<<stu; 另一個原因是,如果使用的多重繼承,編譯器無法確定應轉換為哪個基類,如果兩個基類都提供了函數operator<<()。

3.多重繼承:

多重繼承,顧名思義,就是使用多個基類的繼承(multiple inheritance,MI),描述的是有多個直接基類的類。

4.類模板:

定義:開頭用 template <class Type>  或者 template <typename Type>,模板的具體實現就是執行個體化或具體化。

例如建立一個堆棧類模板樣本:

#pragma once//

#include <iostream>

using namespace std;

template <class Type>

class Stack

{

private:

enum{MAX = 10};

Type items[MAX];

int top;

public:

Stack();

bool IsEmpty();

bool IsFull();

bool Push(const Type &item);

bool Pop(Type & item);

};

template <class Type>

Stack<Type>::Stack()

{

top = 0;

}

template<class Type>

bool Stack<Type>::IsEmpty()

{

return top == 0;

}

template <class Type>

bool Stack<Type>::IsFull()

{

return top == MAX;

}

template <class Type>

bool Stack<Type>::Push(const Type &item)

{

if(top < MAX)

{

items[top++] = item;

return true;

}

else 

return false;

}

template <class Type>

bool Stack<Type>::Pop(Type & item)

{

if(top > 0)

{

item = items[--top];

return true;

}

else

return false;

}

指標類型類模板:既然可以將內建類型或類對象用作類模板的類型,那麼指標可以嗎?答案是肯定的。但是,要注意正確使用指標。

使用指標堆棧的方法之一是,讓調用程式提供一個指標數組,其中每隔指標都指向不同的字串。把這些指標都放在指標堆棧是有意義的,因為每個指標都將指向不同的字串。注意,建立不同指標是調用程式的職責,而不是堆棧的職責。堆棧的認為是管理指標,而不是建立指標。

模板還可以帶參數,例如:template <class Type,int n>,裡面的 int n稱為非類型或運算式參數,但是運算式參數有一定的限制。只可以是整型、枚舉、引用或指標。還可以使用多個型別參數,例如 template <class T1,class T2>

預設類型模板參數:類模板的一項特性是,可以為型別參數提供預設值:

temp <class T1,class T2 = int> 

class Topo

{

...

};

這樣,如果省略了T2的值,編譯器將使用int:

Topo<double,double> m1;    //T1 is double,T2 is double

Topo<double> m2; //T1 is double ,T2 is int

標準模板庫將此使用該特性,將預設類型設定為類

雖然可以為類模板型別參數提供預設值,但不能為函數模板參數提供預設值。不過,可以為非型別參數提供預設值,這對於函數模板和類模板都都是適用的。

模板的其他特性:可用作結構、類或模板類的成員;可將模板用作參數

模板類和友元:模板聲明也可以有友元。模板的友元分為3類:

● 非模板友元

● 約束(bound)模板友元,即友元的類型取決於類被執行個體化時的類型

● 非約束(unbound)模板友元,即友元的所有具體化都是類的每一個具體化的友元

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.