我的隨行筆記11 C++ Primer Plus
1.派生類不能直接訪問基類的私有成員,必須透過基類方法進行。 派生類可以直接訪問(呼叫)基類的公有類方法。
創造派生類物件時,程式先建立基類物件. 派生類建構函式必須使用基類建構函式。
class TablePlayer{ //基類宣告,在.h檔案中
private:
string firstname;
string lastname;
public:
TablePlayer(const string & fn="none", const string & ln="none");
void Name() const;
};
//方法的實現在.cpp檔案中
TablePlayer::TablePlayer(const string & fn, const string & ln) : firstname(fn),
lastname(ln) {} //成員初始化列表法
void TablePlayer::Name() const
{ std::cout<<lastname<<","<<firstname }
class ReatedPlayer: public TablePlayer{ //公有派生類
private:
unsigned int rating;
public:
ReatedPlayer(unsigned int r, const string & fn="none",
const string & ln="none")
ReatedPlayer(unsigned int r,const TablePlayer & tp); //
unsigned int Rating() const {return rating; }
};
//派生類的建構函式
ReatedPlayer::ReatedPlayer(unsigned int r, const string & fn,
const string & ln) : TablePlayer(fn,ln) //將fn,ln引數從派生類建構函式傳遞到基類建構函式
{
rating=r;
}
ReatedPlayer::ReatedPlayer(unsigned int r, const string & fn,
const string & ln) //未呼叫基類建構函式時,等效於使用預設建構函式 : TablePlayer()
{
rating=r;
}
ReatedPlayer::ReatedPlayer(unsigned int r,const TablePlayer & tp):TablePlayer(tp)
{
rating=r;
}
ReatedPlayer::ReatedPlayer(unsigned int r,const TablePlayer & tp):
TablePlayer(tp),rating(r) {}
int main (void){
using std::cout; using std::endl;
TablePlayer player1("Bob", "Boomede");
RatedPlayer rplayer1(1140, "Mallay","Duck"); //建立派生類物件
rplayer1.Name(); //派生類可以直接呼叫基類的公有類方法
}
2.派生類的物件和地址可以賦給基類引用和指標。 但不能將基類的物件和地址賦給派生類引用和指標
TablePlayer & rt=rplayer; TablePlayer * pt= & rplayer; (合法)
3. C++的3種繼承方式:公有繼承 ,保護繼承 和 私有繼承 。公有繼承(is-a 關係 即派生類物件也是一個基類物件)
繼承可以在基類基礎上新增屬性,但不能刪除基類屬性。
4. 同一個方法在派生類和基類中的行為不同,即 同一方法的行為隨上下文而異,這種行為叫多型。
實現多型公有繼承的兩種方法:1) 在派生類中重新定義基類 2)使用虛方法(宣告函式時在前面加關鍵字virtual)具體實現不用加。
在基類中將派生類會重新定義的方法宣告為虛方法. (程式將根據物件型別而不是引用或指標型別來選擇方法版本)
方法在基類中被宣告為虛擬函式後,派生類中將自動成為虛擬函式(也可加virtual指明哪些是虛擬函式)。
為基類宣告一個虛解構函式也是一種慣例。【確保釋放派生類物件時,按正確的順序呼叫解構函式。 先呼叫派生類解構函式,再呼叫基類建構函式】 分析:delete pt ; 釋放記憶體時,先應用派生類預設的解構函式,釋放派生類物件記憶體,再呼叫基類中的虛解構函式來釋放記憶體。 如果不在基類中宣告虛解構函式,直接呼叫基類的解構函式,將只釋放部分記憶體,不會釋放派生類中新的類成員指向的記憶體。
/*基類Brass公有成員函式ViewAcct宣告前無virtual*/
Brass dom(" Dominic Banker",1121,4182.45);//基類物件
BrassPlus dot("Doroty Banker",1238,2592.00);//派生類物件
Brass & b1=dom;
Brass & b2=dot; //派生類可以直接賦給基類
b1.ViewAcct(); // 用Brass::ViewAcct()
b2.ViewAcct(); // 用Brass::ViewAcct()
/*基類Brass公有成員函式ViewAcct宣告前有virtual*/
b1.ViewAcct(); // 用Brass::ViewAcct()
b2.ViewAcct(); // 用BrassPlus::ViewAcct() 根據物件型別而非引用選擇版本
5. 在派生類的成員函式實現中:呼叫基類公有函式時,可直接呼叫如 doubal bal=Balance(),若派生類中虛擬函式ViewAcct()中要呼叫基類的虛擬函式ViewAcct(),要用作用域解析符,應寫為 Brass::ViewAcc()
6. 可以使用一個陣列來表示多種型別的物件,這就是多型性。
Brass * p_client[N]; //Brass[i]指標可以指向Brass物件也可指向BrassPlaus物件
p_client[i]=new Brass(temp,tempnum,tempbal);
p_client[j]=new BrassPlaus(temp,tempnum,tempbal,tmax,trate); //滿足不同的條件用相應的賦值語句
多型性由以下程式碼提供:
for (int i=0;i<N;i++){ p_client[i]->ViewAcct(); }
7.在編譯過程中進行聯編, 稱為靜態聯編 ; (可以直接確定編譯哪個函式)
編譯器必須生成能夠在程式執行時選擇正確的虛擬函式程式碼,稱為動態聯編。
8. 動態聯編可以重新定義類方法, 靜態聯編效率高。
9.編譯器處理虛擬函式的方法:
給每個物件新增一個隱藏成員。這個成員儲存了一個指向函式地址陣列的指標,這種陣列稱為虛擬函式表(vtbl:virtual function table,)。虛擬函式表中儲存了為類物件宣告的虛擬函式的地址。 虛擬函式地址表時一個陣列。
【基類物件中隱含一個指標,該指標指向基類中所有虛擬函式的地址表。派生類物件將隱含一個指向獨立地址表的指標。 如果派生類提供了虛擬函式的新定義,該虛擬函式表將儲存為新的地址,如果派生類沒有重新定義虛擬函式,該vtbl將儲存基類函式的原始地址】
(無論類中的虛擬函式是1個還是10個,只在物件中新增1個地址成員,只是表的大小不同)
10. 友元不能是虛擬函式 (友元不是類成員,只有成員才能是虛擬函式)
11.重新定義的繼承方法並不是過載。
重新定義的繼承方法,應確保與基類的原型完全相同。但如果有返回型別,返回是基類引用或指標,則在派生類繼承方法修改為返回指向派生類的引用或指標。 class Dwelling { public: virtual Dwelling & build (int n) } ; class Hovel:public Dwelling { public: virtual Hovel & build (int n) };
如果基類宣告被過載,則應在派生類中重新定義所有的過載版本。 class Dwelling { public: virtual void showperks ( ) const ; virtual void showperks (int a ) const ; } ; class Hovel:public Dwelling { public: virtual void showperks ( ) const ; virtual void showperks (int a ) const ; };
12. 派生類成員可以直接訪問基類的保護成員,但不能直接訪問基類的私有成員。
對外部世界來說,保護成員和私有成員類似;對派生類來說,保護成員和公有成員類似;
對類資料成員最好採用私有訪問控制,不要使用保護訪問控制;同時透過基類的方法使派生類訪問基類資料;
對於成員函式,保護控制有用,讓派生類訪問公眾不能使用的內部函式
13. 複雜抽象基類(ABC:abstract base class) :只定義介面,不定義實現。至少使用一個純虛擬函式介面,從ABC派生的類將根據派生類的具體特徵,使用常規虛擬函式來實現這種介面。 要成為真正的ABC,必須至少包含一個純虛擬函式。 原型中的=0使虛擬函式成為純虛擬函式。
【當N類和M類有一定的共性,但M類不需要完全繼承N類的資料和方法時,可以將M和N的共性放到ABC中,然後從ABC中派生出N類和M類。 ABC類指標可以同時管理M類和N類物件】 原型使用=0指出類是一個抽象基類。 C++中允許純虛擬函式有定義。
例如: 橢圓和圓兩個類, 共同點是中心座標方法,和移動Move()方法是相同的,但面積Area()是不同的。
在ABC中不能實現Area()方法。 C++透過用純虛擬函式提高未實現的函式,純虛擬函式宣告的結尾處為=0;
當類宣告中包含純虛擬函式時,不應該建立該類的物件。
//橢圓和圓的ABC類
class BaseEllipse{ //宣告中含有純虛擬函式,不能建立BaseEllipse類物件
private:
double x; //橢圓和圓的共性
double y;
public:
BaesEllipse(double x0=0,double y0=0) :x(x0),y(y0){}
virtual ~BaesEllipse();
void Move(int nx,ny) { x=nx; y=ny; } //橢圓和圓的共性
virtual double Area() const=0; //純虛擬函式 橢圓和圓的不同
};
14. 建構函式、解構函式、賦值函式、友元函式不能被繼承。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30239065/viewspace-2716589/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 我的隨行筆記2 C++ Primer Plus筆記C++
- 我的隨行筆記7 C++ Primer Plus筆記C++
- 我的隨行筆記10 C++ Primer Plus筆記C++
- 我的隨行筆記9 C++ Primer Plus筆記C++
- 我的隨行筆記8 C++ Primer Plus筆記C++
- 我的隨行筆記6 C++ Primer Plus筆記C++
- 我的隨行筆記5 C++ Primer Plus筆記C++
- 我的隨行筆記4 C++ Primer Plus筆記C++
- 我的隨行筆記3 C++ Primer Plus 3--指標筆記C++指標
- C++ Primer Plus隨記1C++
- C++ Primer Plus 隨記(第八章)C++
- C++ primer Plus學習筆記(第二章)C++筆記
- 《C++ Primer Plus》15.1 友元 學習筆記C++筆記
- C++ Primer筆記C++筆記
- C++ primer 筆記C++筆記
- 《C++ Primer Plus》16.1 string類 學習筆記C++筆記
- C++ Primer Plus第6版18個重點筆記C++筆記
- 【C++ Primer Plus】學習筆記--第10章 物件和類C++筆記物件
- C++ Primer Plus(四)C++
- C++ Primer Plus(三)C++
- C++ Primer Plus(一)C++
- 《C++ Primer》筆記-#include,#ifndefC++筆記
- C++ Primer Plus 第四章 複合型別 學習筆記C++型別筆記
- c++ primer 第二章閱讀筆記C++筆記
- element-plus隨筆
- 《C++ Primer》學習筆記(六):C++模組設計——函式C++筆記函式
- 《C++ Primer》學習筆記(八):標準 IO 庫C++筆記
- C++ Primer 讀書筆記 - 第一章C++筆記
- 黑馬筆記--C++基礎篇--隨筆筆記C++
- 隨筆 sqlplus / as sysdbaSQL
- 《C++ Primer》讀書筆記(第一章 開始)C++筆記
- C++ Primer 5th筆記(5)chapter5 語句C++筆記APT
- C++筆記(11) 智慧指標C++筆記指標
- 4.11隨筆
- C++ Primer 第二章 學習筆記及習題答案C++筆記
- 隨筆記筆記
- C++ Primer!C++的“倚天劍”C++
- 筆記:《C++ Primer 中文版(第5版)》 第1章 開始筆記C++