C++繼承一之公有繼承

gaopengtttt發表於2016-08-09
一般來說一個類可以繼承於另外一個類,分別叫做派生類和基類,
派生類繼承了基類的公有成員和保護成員以及實現,而私有成員只能透過
基類的公有方法進行訪問
派生類應該包含如下資訊:
1、繼承類建構函式
2、需要額外增加的成員以及實現

我們引用C++ primer plus中的例子,當然這些例子我都是手動打過一遍的
<lastname<<", "<<firstname;="" }="" rateplayer::rateplayer(unsigned="" int="" r,const="" string="" &fn,const="" &ln,bool="" ht):tabletennisplayer(fn,ln,ht),rating(r){} <player3.rating();=""

點選(此處)摺疊或開啟

  1. #ifndef TABTEEN_H_
  2. #define TABTEEN_H_
  3. #include<iostream>
  4. using namespace std;

  5. class TableTennisPlayer
  6. {
  7.         private:
  8.                 string firstname;
  9.                 string lastname;
  10.                 bool hasTable;
  11.         public:
  12.                 TableTennisPlayer(const string &fn = "none",const string & ln ="none",bool ht=false);
  13.                 void Name() const;
  14.                 bool HasTable() const
  15.                 {return hasTable;};
  16.                 void ResetTable(bool v)
  17.                 {hasTable = v;};
  18. };

  19. class RatePlayer:public TableTennisPlayer
  20. {
  21.         private:
  22.                 unsigned int rating;
  23.         public:
  24.                 RatePlayer(unsigned int r=0,const string & fn="none",const string& ln="none",bool ht=false);
  25.                 RatePlayer(unsigned int r,const TableTennisPlayer& tp);
  26.                 unsigned int Rating() const
  27.                 {return rating;}
  28.                 void ResetRaing(unsigned int r)
  29.                 {rating = r;}
  30. };

  31. #endif

  32. TableTennisPlayer::TableTennisPlayer (const string& fn,const string &ln,bool ht):firstname(fn),lastname(ln),hasTable(ht){}
  33. void TableTennisPlayer::Name() const
  34. {
  35.         std::cout<<lastname<<", "<<firstname;
  36. }
  37. RatePlayer::RatePlayer(unsigned int r,const string &fn,const string &ln,bool ht):TableTennisPlayer(fn,ln,ht),rating(r){}
  38. //這裡注意必須使用初始化列表的方式進行基類的初始化及TableTennisPlayer(fn,ln,ht)是必須的當然這裡rating(r)不是必須的
  39. RatePlayer::RatePlayer(unsigned int r,const TableTennisPlayer& tp):TableTennisPlayer(tp),rating(r){}
  40.  //這裡注意TableTennisPlayer(tp)呼叫了預設的複製建構函式,每個類都包含一個預設的複製建構函式

  41. 主函式

  42. #include<iostream>
  43. #include "tabtenn0.h"
  44. using namespace std;

  45. int main(void)
  46. {
  47.         TableTennisPlayer player1("Chuck","Blizzard",true);
  48.         TableTennisPlayer player2("Tara","Boomdea",true);
  49.         RatePlayer player3(1111,"gaopeng","Yjf",false);
  50.         player1.Name();
  51.         if(player1.HasTable())
  52.                 cout<<": has a table.\n";
  53.         else
  54.                 cout<<": hasn't a table.\n";
  55.         player2.Name();
  56.         if(player2.HasTable())
  57.                 cout<<": has a table\n";
  58.         else
  59.                 cout<<": hasn't a table.\n";

  60.         player3.Name();//TableTennisPlayer.Name()
  61.         cout<<" sorce: "<<player3.Rating();
  62.         if(player3.HasTable())
  63.                 cout<<": has a table\n";
  64.         else
  65.                 cout<<": hasn't a table.\n";

  66.         return 0;
  67. }




這裡player3物件的類是RatePlayer基類是TableTennisPlayer,Name和HasTable方法都是TableTennisPlayer繼承而來,
而Rating是在繼承類RatePlayer中定義的

注意點:
1、RatedPlayer::RatedPlayer(unsigned int r,const string &fn,const string &ln,bool ht):TableTennisPlayer(fn,ln,ht),rating(r){}
這裡注意必須使用初始化列表的方式進行基類的初始化及TableTennisPlayer(fn,ln,ht)是必須的當然這裡rating(r)不是必須的 
   可以{rating = r;}宣告   
下面的型別必須使用初始化列表的方式進行初始化
當使用如下方式的時候需要使用建構函式列表初始化成員
  1、const 成員
  2、引用&成員
  3、繼承類的基類初始化
  4、本生就是類的成員
詳細見
http://blog.itpub.net/7728585/viewspace-2122388/ 第8部分
2、RatePlayer(unsigned int r,const TableTennisPlayer& tp):TableTennisPlayer(tp),rating(r){} 
這裡注意TableTennisPlayer(tp)呼叫了預設的複製建構函式,每個類都包含一個預設的複製建構函式,
在使用new等動態分配的時候顯示定義深度複製建構函式是必須的,但是這裡預設即可
詳細見
http://blog.itpub.net/7728585/viewspace-2121213/ 第2部分深度複製
3、RatedPlayer::RatedPlayer(unsigned int r,const string &fn,const string &ln,bool ht):rating(r){}
注意這裡沒有呼叫建構函式,編譯器將對基類使用預設的建構函式,也就是什麼都不做,但是這樣顯然沒有意義
在這裡。
詳細見
http://blog.itpub.net/7728585/viewspace-2120608/
下面是派生類建構函式相關要點
1、派生類建構函式需要呼叫基類建構函式初始化基類,並且在初始化列表中
2、派生類建構函式應該初始化新增的資料成員
3、派生類建構函式在初始化前就需要初始化基類,所以必須在初始化列表中
另外在解構函式中,程式會先呼叫派生類解構函式然後呼叫基類解構函式

其次,注意當基類的指標或者引用物件可以指向繼承類的物件,因為繼承類中一定包含了基類有的全部的資訊,
但是反過來繼承類的指標或者引用不你能指向基類的物件,因為基類並不包含繼承類的全部資訊,比如RatePlayer
中的rating在基類TableTennisPlayer中是不存在的,所以如下是成立的
同樣我們知道預設的複製建構函式定義為
TableTennisPlayer(TableTennisPlayer& in)
但是由於TableTennisPlayer& 可以指向 RatePlayer&
所以TableTennisPlayer(RatePlayer& in)是成立的
也就是說
RatePlayer player3(1111,"gaopeng","Yjf",false);
TableTennisPlayer p3(player3);
成立
詳細見
http://blog.itpub.net/7728585/viewspace-2121213/ 第2部分深度複製
同時
RatePlayer player3(1111,"gaopeng","Yjf",false);
TableTennisPlayer p4;
p4=player3;
也是成立的
呼叫預設的等值複製函式
原型
TableTennisPlayer& operator=(const TableTennisPlayer& st)
由於TableTennisPlayer&可以指向 RatePlayer&
所以TableTennisPlayer& operator=(const RatePlayer& st)
詳細見:
http://blog.itpub.net/7728585/viewspace-2122388/ 第二部分
我們可以試一下,在原有的程式碼中加入: 
<endl;
<endl;

點選(此處)摺疊或開啟

  1. TableTennisPlayer p1(player3);
  2.      TableTennisPlayer p2;
  3.      p2=player3;
  4.      p1.Name();
  5.      cout<<endl;
  6.      p2.Name();
  7.     cout<<endl;
  8.    return 0;
</endl;
輸出為:
Yjf, gaopeng
Yjf, gaopeng
沒有問題
</endl;
</lastname<

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2123224/,如需轉載,請註明出處,否則將追究法律責任。

相關文章