C ++ Primer第13章クラスの継承

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-関係は、派生クラスオブジェクトが基本クラスオブジェクトでもあることを意味します)

  継承は基本クラスに属性を追加できますが、基本クラスの属性を削除することはできません。

4.派生クラスと基本クラスの同じメソッドの動作が異なります。つまり、同じメソッドの動作はコンテキストによって異なります。この動作は多態性と呼ばれます。

  •    多態的なパブリック継承を実装するには、2つの方法があります。1)派生クラスの基本クラスを再定義します。2)仮想メソッドを使用します(関数を宣言するときにキーワードvirtualの前に置きます)。
  •  派生クラスの再定義されたメソッドを基本クラスの仮想メソッドとして宣言します(プログラムは、参照タイプやポインタータイプではなく、オブジェクトタイプに基づいてメソッドバージョンを選択します)
  • メソッドが基本クラスで仮想関数として宣言されると、そのメソッドは自動的に派生クラスの仮想関数になります(仮想関数を追加して、どの仮想関数であるかを示すこともできます)。
  • 基本クラスの仮想デストラクタを宣言することも慣例です。[派生クラスオブジェクトを解放するときは、必ず正しい順序でデストラクタを呼び出してください。最初に派生クラスのデストラクタを呼び出し、次に基本クラスのコンストラクタを呼び出します]分析:削除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.派生クラスのメンバー関数の実装:基本クラスのパブリック関数を呼び出すときに、派生クラスの仮想関数ViewAcct()が基本クラスの仮想関数ViewAcct()を呼び出す必要がある場合は、doubal bal = Balance()などを直接呼び出すことができます。スコープリゾルバーを使用するには、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:仮想関数テーブル)と呼ばれる関数アドレスの配列へのポインターを保持します仮想関数テーブルには、クラスオブジェクトに対して宣言された仮想関数のアドレスが格納されます。仮想関数アドレステーブルは配列です。
  • [基本クラスオブジェクトに暗黙のポインタがあります。これは、基本クラスのすべての仮想関数のアドレステーブルを指します。派生クラスオブジェクトは、独立したアドレステーブルへのポインタを意味します。          派生クラスが仮想関数の新しい定義を提供する場合、仮想関数テーブルは新しいアドレスとして保存されます。派生クラスが仮想関数を再定義しない場合、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:抽象基本クラス):インターフェースのみを定義し、実装は定義しません。少なくとも1つの純粋な仮想関数インターフェイスが使用され、ABCから派生したクラスは、従来の仮想関数を使用して、派生クラスの特定の特性に従ってこのインターフェイスを実装します真のABCであるためには、少なくとも1つの純粋な仮想関数が含まれている必要があります。プロトタイプの= 0は、仮想関数を純粋な仮想関数にします。

[NクラスとMクラスに一定の共通点があるが、MクラスがNクラスのデータとメソッドを完全に継承する必要がない場合は、MとNの共通性をABCに入れて、ABCからNクラスとMクラスを導出できます。 。ABCクラスポインタはMクラスとNクラスのオブジェクトを同時に管理できます] プロトタイプuse = 0は、クラスが抽象基本クラスであることを示します。C ++では、純粋な仮想関数を定義できます。

例:楕円と円の2つのクラス、共通点は中心座標メソッドです。これはMove()メソッドと同じですが、面積()が異なります。

           Area()メソッドはABCでは実装できません。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.コンストラクタ、デストラクタ、割り当て関数、フレンド関数は継承できません。

 

おすすめ

転載: blog.csdn.net/lvliang2017232003/article/details/88804365