C++ 繼承特性

——派生類須要本身的構造函數。函數

    派生類中能夠根據須要添加額外的數據成員和成員函數,甚至能夠給予繼承的原成員函數新的定義。this

  基類指針或引用可指向派生對象,反過來則只能使用強制類型轉換。spa

  派生類對象可以使用基類的非私有成員。指針

  可以使用派生對象初始化基類對象或賦值。code

  通常不容許將基類對象賦給派生類對象(上面第三條),特殊狀況下能夠。對象

  已有派生類對象初始化建立的派生類對象。blog

  已有派生類對象給另外一個派生類對象賦值。繼承

  派生類對象的析構函數被調用後會自動調用基類的析構函數。內存

  C++11增長了容許繼承構造函數的機制,但派生類默認不能繼承構造函數和析構函數。ci

 

class RatedPlayer : public TableTennisPlayer
 {
 private:
     unsigned int rating;    // add a data member
 public:
     RatedPlayer (unsigned int r = 0, const string &fn = "none", const string &ln = "none", bool ht = false);
     RatedPlayer (unsigned int r, const TableTennisPlayer &tp);
     unsigned int Rating() const { return rating; }    // add a method
     void ResetRating (unsigned int r) { rating = r; }    // add a method
};

   構造函數必須給新成員和繼承的成員提供數據。

RatedPlayer::RatedPlayer(unsigned int r, const string &fn, const string &ln, bool ht) : TableTennisPlayer(fn, ln, ht)
{
    rating = r;
}
  • 派生類構造函數必須使用基類構造函數,建立派生類對象時,程序首先建立基類對象(初始化繼承的數據成員)而後再調用派生類構造函數。C++使用成員初始化列表語法完成該操做。
  • 如沒有調用基類構造函數,那麼將隱式調用基類的默認構造函數。除非要使用默認構造函數,不然應顯示調用正確的基類構造函數。

  派生類對象過時時,程序將首先調用派生類析構函數,而後再自動調用基類析構函數。

  要使用派生類,程序必需要能訪問基類聲明。

  派生類對象可使用基類的方法,條件是方法不是私有的(即公有和保護)。

 

  基類指針能夠在不進行顯示類型轉換的狀況下指向派生類對象;基類引用能夠在不進行顯示類型轉換的狀況下引用派生類對象

RatedPlayer rplayer(1140, "Mallory", "Duck", true);
TableTennisPlayer &rt = rplayer;
TableTennisPlayer *pt =&rplayer;
rt.Name();    // invoke Name() with reference
pt->Name();    // invoke Name() with pointer

  不能夠將基類對象和地址賦給派生類引用和指針,除非使用強制轉換(友元函數不是成員函數所以不能被繼承,但欲使用基類的友元函數時可以使用此方法,但要當心用錯)。

  基類聲明的函數引用參數或指針參數可用於值爲基類對象或派生類對象以及它們的地址的狀況。

void Show(const TableTennisPlayer &rt)
{
    ...
}

 

 

TableTennisPlayer player1("Tara", "Boomdea", false);
RatedPlayer rplayer1(1140, "Mallory", "Duck", true);
Show(player1);    // works with TableTennisPlayer argument
Show(rplayer1);    // works with RatedPlayer argument

  省略形參爲const TableTennisPlayer *rt的狀況,與上類似。

  引用兼容性屬性:能夠將基類對象初始化爲派生類對象。

RatedPlayer olaf1(1840, "Olaf", "Loaf", true);
TableTennisPlayer olaf2(olaf1);

   匹配的構造函數的原型:

TableTennisPlayer(const RatedPlayer &);    // doesn't exit

 

  類中並無該構造函數,但存在隱式複製構造函數:

// implicit copy constructor
TableTennisPlayer(const TableTennisPlayer &);

   即它將olaf2初始化爲嵌套在RatedPlayer對象olaf1中的TableTennisPlayer對象(使用派生類中嵌套的基類對象對目標基類對象進行初始化)

  一樣,也能夠將派生對象賦給基類對象:

RatedPlayer olaf1(1840, "Olaf", "Loaf", true);
TableTennisPlayer winner;
winner = olaf1;    // assign derived to base object

   在這種狀況下,程序使用隱式重載賦值運算符:

TableTennisPlayer &operator=(const TableTennisPlayer &) const;

   與上相似,使用派生類中嵌套的基類對象對目標基類對象進行按成員賦值。

 

  特殊的用基類對象給派生類對象賦值的狀況

  若是派生類包含了將基類對象轉換爲派生類對象的構造函數,或派生類定義了將基類對象賦給派生類對象的賦值運算符,則能夠用派生類對象給基類對象賦值。

 

  用已有的派生類對象初始化建立的派生類對象

  複製類成員或繼承的類組件時,則是使用該類的複製構造函數完成的,對於繼承的基類對象來講也是合適的。

  用已有的派生類對象給另外一個派生類對象賦值

  按成員賦值,調用類成員賦值運算符,使用基類的賦值運算符來對基類組件(繼承的基類對象)進行賦值

 

  若派生類使用了動態內存分配,派生類的析構函數、複製構造函數、複製運算符都必須使用相應的基類方法來處理基類元素(顯示調用基類構造函數和複製運算符): 

  • 對於析構函數,這是自動完成的。
  • 對於複製構造函數,這是在初始化成員列表中調用基類的複製構造函數來完成的;若是不這麼作,將自動調用基類的默認構造函數。
  • 對於複製運算符,這是經過使用做用域解析運算符顯示地調用基類的賦值運算符來完成的:

 

hasDMA &hasDMA::operator=(const hasDMA &has)
{
    if (this == &hs)
        return *this;
    baseDMA::operator=(hs);    // copy base portion
    ...
    return *this;    
}

  

  ---

相關文章
相關標籤/搜索