c++ 的類 和 類繼承, 什么是c++中的基類和派生類?


 

閑雲潭影日悠悠,物換星移幾度秋

你既然已經做出了選擇, 又何必去問為什么選擇。鬼谷絕學的要義, 從來都不是回答, 而是抉與擇

普通類

#ifndef TABTENN0_H_
#define TABTENN0_H_

#include <string>

using namespace std;

class TableTennisPlayer
{
private:
    string firstname;
    string lastname;
    bool hasTable;
public:
    TableTennisPlayer (
      const string & fn = "none",
      const string & ln = "none",
      bool ht = false
    );
    void Name() const;
    bool HasTable() const {return hasTable;};
    void ResetTable(bool v) {hasTable = v;};
};


#endif
tabtenn0.h

 

#include <iostream>
#include <string>
#include "tabtenn0.h"

using namespace std;

TableTennisPlayer::TableTennisPlayer(const string & fn, const string & ln, bool ht): firstname(fn), lastname(ln), hasTable(ht) {}

void TableTennisPlayer::Name () const
{
    std::cout << lastname << "," << firstname ;
}
tabtenn0.cpp

 

#include <iostream>
#include "tabtenn0.h"

using namespace std;

int main (int argc, char const *argv[])
{
    TableTennisPlayer player1("Chuck", "Blizzard", true);
    TableTennisPlayer player2("Tara", "Boomdea", false);
    player1.Name();
    if (player1.HasTable()){
      std::cout << ":has a table." << '\n';
    }else{
      std::cout << ":hasn't a table." << '\n';
    };
    player2.Name();
    if (player2.HasTable()){
      std::cout << ":has a table" << '\n';
    }else{
      std::cout << ":hasn't a table." << '\n';
    };
    return 0;
}
usett0.cpp

 

繼承類

基類的private成員都不能被派生類訪問。

聲明為public的方法和屬性可以被隨意訪問;

聲明為protected的方法和屬性只能被類本身和其子類訪問;

而聲明為private的方法和屬性只能被當前類的對象訪問。  

 

#include <iostream>
#include <string>

using namespace std;

class Father
{
private:
        string first_name;
        string last_name;
public:
        Father(string fn, string ln): first_name(fn), last_name(ln) {};
        void Name() {std::cout << first_name  << ","<< last_name << '\n';};
};


class Son: public Father  // 這句很重要呀
{
private:

public:
        Son(string an, string bn):Father(an, bn){};
};

int main(int argc, char const *argv[])
{
    // Father father("張三", "李四");
    // father.Name();

    Son son("張三", "李四");
    son.Name();

    return 0;
}
繼承類寫法

 

下面這個是兩種展示調用基類方法的方式很有意思, 設計到拷貝構造和深淺拷貝, 有興趣可以百度下

#ifndef TABTENN1_H_
#define TABTENN1_H_
#include <string>

using namespace std;

class TableTennisPlayer
{
private:
    string firstname;
    string lastname;
    bool hasTable;
public:
    TableTennisPlayer(const string & fn = "none",
                      const string & ln = "none",
                      bool ht = false);
    void Name() const;
    bool HasTable() const {return hasTable;};
    void ResetTable(bool v) {hasTable = v;};
};


class RatedPlayer: public TableTennisPlayer
{
private:
  unsigned int rating;
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;};
  void ResetRating (unsigned int r) {rating = r;};

};



#endif
tabtenn1.h

 

#include <iostream>
#include "tabtenn1.h"

TableTennisPlayer::TableTennisPlayer (
  const string & fn,
  const string & ln,
  bool ht):firstname(fn), lastname(ln), hasTable(ht) {}

void TableTennisPlayer::Name() const
{
    std::cout << lastname << ", " << firstname ;
}

RatedPlayer::RatedPlayer (
  unsigned int r,
  const string & fn,
  const string & ln,
  bool ht): TableTennisPlayer(fn, ln, ht){
  rating = r;
}

RatedPlayer::RatedPlayer(
  unsigned int r,
  const TableTennisPlayer & tp
):TableTennisPlayer(tp), rating(r) {}

/*
問題是上面這個類方法函數:
RatedPlayer::RatedPlayer(
  unsigned int r,
  const TableTennisPlayer & tp
):TableTennisPlayer(tp), rating(r) {}

的TableTennisPlayer(tp) 是不是等於 TableTennisPlayer = tp的意思

但是usett1.cpp 里面傳入以后player1的作用是什么?

*/
tabtenn1.cpp

 

#include <iostream>
#include <string>
#include "tabtenn1.h"

using namespace std;

int main(int argc, char const *argv[])
{

    /*
    TableTennisPlayer player1("Tara", "Boomdea", false);
    RatedPlayer rplayer1(1140, "Mallory", "Duck", true);
    rplayer1.Name();


    if (rplayer1.HasTable())
    {
        std::cout << ": has a table." << '\n';
    }else
    {
        std::cout << ": hasn't a table." << '\n';
    }

    std::cout << "Name:";
    rplayer1.Name();

    std::cout << "; Rating : " << rplayer1.Rating() << '\n';

    */
    TableTennisPlayer player1("Tara", "Boomdea", false);
    RatedPlayer rplayer2 (1212, player1);

    std::cout << "Name: ";
    rplayer2.Name();

    std::cout << "; Rating : " << rplayer2.Rating() << '\n';


    return 0;
}
usett1.cpp

 

 

 

分為三種:

{

  公有繼承,

  保護繼承,

  私有繼承

}

從一個類派生出另一個類時, 原始類成為基類, 繼承類成為派生類。粗俗的講:子繼承父, 父就是基類, 子就是派生類

這說明繼承, 首先需要一個基類。

對於公有派生, 派生類對象包含基類對象, 基類的公有成員將成為派生類的公有成員;

基類的私有部分也將成為派生類的一部分, 但只能通過基類的公有和保護方法訪問。換句話說: "派生類不能訪問基類的私有成員, 必須通過基類的方法進行"

 

簡單寫法

class RatedPlayer: public TableTennisPlayer
{
  private:

  public:

};

 

構造函數

RatedPlayer::RatedPlayer(
  unsigned int r, 
  const string & fn, 
  const string & fn, 
  cosnt string & ln, 
  bool ht
): TableTennisPlayer(fn, ln, ht) // 初始化基類構造函數, 或者說成員初始化列表
{
    rating = r;
}

// 如果賦值RatedPlayer rplayer(1140, "Mallory", "Duck", true),
// 同時將“Mallory”, "Duck" 和 true賦給fn、ln和ht作為實參傳遞給TableTennisPlayer構造函數

 

 

如果省略成員初始化列表, 將會怎么樣?

RatedPlayer::RatedPlayer(
  unsigned int r, 
  const string & fn, 
  const string & fn, 
  cosnt string & ln, 
  bool ht
)
{
    rating = r;
}
如果不調用基類構造函數, 與下面代碼等效, 程序將使用默認的基類構造函數
RatedPlayer::RatedPlayer(
  unsigned int r, 
  const string & fn, 
  const string & fn, 
  cosnt string & ln, 
  bool ht
): TableTennisPlayer() // 程序將使用默認的基類構造函數, 上面代碼與此等效
{
    rating = r;
}

 

注意: 除非要使用默認構造函數, 否則應顯式調用正確的基類構造函數。

RatedPlayer::RatedPlayer(
  unsigned int r, 
  const string & fn, 
  const string & fn, 
  cosnt string & ln, 
  bool ht
): TableTennisPlayer(tp) 
{
    rating = r;
}

 

 

 

未完待續...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM