c++コード再利用-プライベート継承(学習ノート)

13960 ワード

継承のガイドライン
  • 派生クラスはベースクラスのインタフェースを継承しない>ベースクラスの公有メソッドが派生クラスのプライベートメソッド
  • となるからである.
  • 派生クラスは
  • を継承する.
    studentクラスの例
    1.プライベート継承の宣言
    1 class student:private std::string,private std::valarray < double >
    
    2 {  
    
    3     public:
    
    4     ....
    
    5 };

    注意すべき点:
  • privateはデフォルト値です.ここで省略すると、プライベート継承
  • も発生します.
  • 複数のベースクラスの継承を使用するmultiple inheritanceとも呼ばれる
  • を次のセクションで理解する.
  • の最も重要な点:studentという新しいクラスはプライベートデータを必要とせず、プライベート継承は彼に2つの名前のないサブオブジェクトメンバー
  • を提供した.
     
    2.ベースクラスコンポーネントの初期化
    なぜなら、プライベート継承は派生クラスに2つの名前のないサブオブジェクトメンバーを提供するため、以前のようにオブジェクト名を使用して初期化することはできません.これも2つのstudentクラスの2番目の違いです.
  • オブジェクト名ではなくクラス名を使用
    1 student(const char* str,const double* pD, int n)
    
    2     :std::string(str),ArrayDb(pd,n){}

    説明:typedef std::valarrayArrayDb
  • ArrayDbはstd::valarrayDbの別名
  • ヘッダファイルは、以下に示す
     1 #ifndef STUDENT_H_
    
     2 #define STUDENT_H_
    
     3 
    
     4 #include
    
     5 #include
    
     6 #include
    
     7 
    
     8 class student:private std::string,private std::valarray
    
     9 {
    
    10 private:
    
    11     typedef std::valarray ArrayDb;
    
    12     std::ostream & arr_out(std::ostream& os)const;
    
    13 public:
    
    14     student():std::string("Null Student"),ArrayDb(){}
    
    15     explicit student(const std::string& s)
    
    16         :std::string(s),ArrayDb(){}
    
    17     explicit student(int n):std::string("Nully"),ArrayDb(n){}
    
    18     student(const std::string& s,int n)
    
    19         :std::string(s),ArrayDb(n){}
    
    20     student(const std::string & s,ArrayDb & a)
    
    21         :std::string(s),ArrayDb(a){}
    
    22     student(const char* str,const double* pd,int n)
    
    23         :std::string(str),ArrayDb(pd,n){}
    
    24     ~student(){}
    
    25     double average() const;
    
    26     double & operator[](int i);
    
    27     double operator[](int i)const;
    
    28     const std::string & Name() const;
    
    29     //friends
    
    30     friend std::istream & operator>>(std::istream & is,
    
    31                               student & stu);
    
    32     friend std::istream & getline(std::istream & is,
    
    33                               student & stu);
    
    34     friend std::ostream & operator<<(std::ostream & os,
    
    35                              const student & stu);
    
    36 };
    
    37 #endif

    プログラムの説明:
    1 student(const std::string & s,ArrayDb & a)
    
    2         :std::string(s),ArrayDb(a){}

    valarrayの概念では、valarrayオブジェクトには多くの構造関数があり、そのうちの1つは以下の通りです.
    1 valarray< double >v4(gpa,4);
  • は、4つの要素の配列を宣言し、gap(valarrayのオブジェクトでもある)の最初の4つの要素で初期化します.

  • 3.ベースクラスへのアクセス方法
    プライベート継承を使用する場合、ベースクラスのメソッドをどのように使用しますか?
      :                  ,  ,                    

    2つのコードの比較を見てみましょう.(1)は
     1 double student::average()const
    
     2 {
    
     3     if(scores.size()>0)
    
     4     {
    
     5         return scores.sum()/scores.size();
    
     6     }
    
     7     else
    
     8     {
    
     9         return 0;
    
    10     }
    
    11 }

    (2)私有相続
     1 double student::average()const
    
     2 {
    
     3     if(ArrayDb::size()>0)
    
     4     {
    
     5         return ArrayDb::sum()/ArrayDb::size();
    
     6     }
    
     7     else
    
     8     {
    
     9         return 0;
    
    10     }
    
    11 }
  • は、派生クラスのメソッドでのみベースクラスのメソッドを使用することができるとともに、クラス名と役割ドメイン解析演算子を使用してベースクラスメソッド
  • を呼び出す.
    4.ベースクラスオブジェクトへのアクセス
    まずコードセグメントをレビューする
    1 const string & student::Name()const
    
    2 {
    
    3     return name;
    
    4 }

    これは、stringオブジェクトで名前がnameに設定されたバージョンのデータ・メンバーの名前を返すためのものですが、プライベート継承では、名前のない2つのサブオブジェクト・メンバーが提供されていることを知っています.では、ベース・クラスのオブジェクトにどのようにアクセスすればいいのでしょうか.
  • 強制タイプ変換の具体的なコードフラグメントは以下の通りである.
    1 const string & student::Name()const
    
    2 {
    
    3 return (const string &)*this
    
    4 }

    説明:
  • は、studentがstringから派生したことが明らかであるため、強制タイプ変換を使用してstudentオブジェクトをstringオブジェクトに変換することができ、変換結果:継承されたstringオブジェクト
  • thisポインタはメソッドを呼び出すオブジェクトを指し、*thisはオブジェクト自体であり、このコードではstudent、
  • を指す.
  • コンストラクション関数による新しいオブジェクトの作成を回避するために、強制タイプ変換を使用して参照を作成し、メソッドを呼び出したstudentオブジェクトの継承stringオブジェクトを指す戻り参照を返すことができます.

  • 5.ベースクラスにアクセスするメタ関数クラス名と役割ドメイン解析演算子を使用してメタ関数を呼び出す場合、メタ関数は概念的にメンバー関数ではないため、メタ関数には適切ではありません.
  • 解決策:派生クラスの参照表示をベースクラスの参照に変換し、友元関数を呼び出す.

  • コードクリップは次のとおりです.
    1 ostream & operator<<(std::ostream & os,const student & stu)
    
    2 {
    
    3     os<< "scores for "<< (const string &)stu<< ":
    "; 4 return os; 5 }

    覚えておいてください.stuがstringの参照に自動的に変換されないのは、変換を表示していない派生クラスの参照またはポインタが、ベースクラスに値を付与できない参照またはポインタであるからです.(どういう意味ですか?)