C++ Notes-Inheritance-04

4592 ワード

派生クラスの構造と構造
一、派生クラスの構造関数
1、デフォルト
(1)ベースクラスのコンストラクタは継承されない
(2)派生クラスは独自のコンストラクタを定義する必要がある.
2、C++11規定
(1)using文でベースクラス構築関数を継承できる
(2)ただしベースクラスから継承されたメンバーのみ初期化可能
派生クラス新規メンバーは、クラス内の初期値で初期化できます.
(3)文法形式:
using B::B
推奨:派生クラスに独自の新規メンバーがあり、コンストラクション関数で初期化する必要がある場合は、派生クラスがコンストラクション関数をカスタマイズします.
3、ベースクラスのコンストラクション関数を継承しない場合、派生クラスコンストラクション関数の役割:
(1)派生クラス新規メンバー:派生クラス定義コンストラクタ初期化
(2)継承されたメンバー:ベースクラス構築関数を自動的に呼び出して初期化する
(3)派生クラスのコンストラクタはベースクラスのコンストラクタにパラメータを渡す必要がある
4、単独相続
派生クラスに直接ベースクラスが1つしかない場合は、単一継承であり、単一継承の場合、派生クラスのコンストラクション関数は直接ベースクラスコンストラクション関数にパラメータを渡すだけです.
単一継承時のコンストラクション関数の定義と構文
派生クラス名:派生クラス名(ベースクラスに必要なパラメータ、このクラスメンバーに必要なパラメータ):ベースクラス名(パラメータテーブル)、このクラスメンバー初期化リスト
{
//その他初期化
}
Ex:
#include<iostream>
using namespace std;
class B {
public:
    B();
    B(int i);
    ~B();
    void print() const;
private:
    int b;
};

B::B() {
    b=0;
    cout << "B's default constructor called." << endl;
}
B::B(int i) {
    b=i;
    cout << "B's constructor called." << endl;
}
B::~B() {
    cout << "B's destructor called." << endl;
}
void B::print() const {
    cout << b << endl;
}

class C: public B {
public:
    C();
    C(int i, int j);
    ~C();
    void print() const;
private:
    int c;
};
C::C() {
    c = 0;
    cout << "C's default constructor called." << endl;
}
C::C(int i,int j): B(i), c(j){
    cout << "C's constructor called." << endl;
}

C::~C() {
    cout << "C's destructor called." << endl;
}
void C::print() const {
    B::print();
    cout << c << endl;
}

int main() {
    C obj(5, 6);
    obj.print();
    return 0;
}

5、マルチ継承
マルチ継承では、複数の直接ベースクラスがあり、ベースクラスのコンストラクション関数を継承しない場合は、派生クラスコンストラクション関数伝達パラメータ
複数継承時のコンストラクション関数の定義構文:
派生クラス名::派生クラス名(パラメータテーブル):ベースクラス名1(ベースクラス1初期化パラメータテーブル)、
ベースクラス名2(ベースクラス2初期化パラメータテーブル)、
                                                       ...
ベースクラス名n(ベースクラスn初期化パラメータテーブル)、
このクラスのメンバーの初期化リスト{//その他の初期化;};
6.派生クラスのベースクラスの構築関数
(1)ベースクラスにデフォルトのコンストラクタがある場合
派生クラス構築関数は、ベースクラス構築関数にパラメータを渡さなくてもよい
派生クラスのオブジェクトを作成すると、ベースクラスのデフォルトのコンストラクション関数が呼び出されます.
(2)ベースクラスにおけるパラメータ付きコンストラクタを実行する必要がある場合
派生クラス構築関数は、ベースクラス構築関数にパラメータを提供する必要があります.
7、オブジェクトメンバーが複数継承されている場合の派生クラスのコンストラクタ定義構文
派生クラス名:派生クラス名(パラメータ):
ベースクラス名1(パラメータ)、ベースクラス名2(パラメータ)、...、ベースクラス名n(パラメータ)、
このクラスのメンバー(オブジェクトメンバーを含む)の初期化リスト
{
//その他初期化
};
8、構築関数の実行順序
(1)ベースクラス構築関数の呼び出し
順序は、継承されたときに宣言された順序(左から右)に従います.
(2)初期化リストのメンバーを初期化する
順序は、クラスで定義された順序(リストを初期化する順序ではありません)に従います.
オブジェクトメンバーが初期化されると、その属するクラスのコンストラクション関数が自動的に呼び出されます.初期化リストからパラメータを指定します.
(3)派生クラスを実行するコンストラクション関数体の内容
二、派生クラスの構造関数の例
Derivedクラス継承の順序(左から右)は、まずベースクラス2のコンストラクション関数、さらにベースクラス1のコンストラクション関数、さらにベースクラス3のコンストラクション関数である
次に、クラスで定義された順序で、まずベースクラス1のコンストラクション関数、次にベースクラス2のコンストラクション関数、最後にベースクラス3のコンストラクション関数
#include <iostream>
using namespace std;
class Base1 {//  Base1,       
public:
    Base1(int i) 
  { cout << "Constructing Base1 " << i << endl; }
};
class Base2 {//  Base2,       
public:
    Base2(int j) 
  { cout << "Constructing Base2 " << j << endl; }
};
class Base3 {//  Base3,       
public:
    Base3() 
  { cout << "Constructing Base3 *" << endl; }
};

class Derived: public Base2, public Base1, public Base3 {
public: 
    Derived(int a, int b, int c, int d): Base1(a), member2(d), member1(c), Base2(b)
  //                 
    { }
private:
    Base1 member1;
    Base2 member2;
    Base3 member3;
};

int main() {
    Derived obj(1, 2, 3, 4);
    return 0;
}

三、派生クラスの複製構造関数
1.派生クラスが複製構造関数を定義していない場合
(1)コンパイラは必要に応じて暗黙のレプリケーションコンストラクタを生成する
(2)ベースクラスのレプリケーションコンストラクタを先に呼び出す
(3)派生クラスの新規メンバーのコピー
2、派生クラスが複製構造関数を定義した場合
(1)基本クラスのレプリケーションコンストラクタにパラメータを渡すのが一般的である.
(2)レプリケーションコンストラクタは、派生クラス定義のメンバーを初期化したり、ベースクラスのレプリケーションコンストラクタに渡したりするために1つのパラメータしか受け入れられません.
(3)ベースクラスの複製コンストラクタパラメータタイプはベースクラスオブジェクトの参照であり,実パラメータは派生クラスオブジェクトの参照であってもよい
(4)例えばC::C(const C&c 1):B(c 1){...}
四、派生クラスの構造関数
(1)コンストラクション関数は継承されません.派生クラスが必要な場合は、コンストラクション関数を自分で宣言します.
(2)宣言メソッドは継承関係がない場合のクラスの構造関数と同じである.
(3)ベースクラスの構造関数を表示せずに呼び出すと,自動的に暗黙的に呼び出される.
(4)派生クラスの解析関数を実行した関数体から,ベースクラスの解析関数を呼び出す.
構造関数の実行順序は構造関数とは逆であり、例えば二の例では、構造関数の実行順序は構造関数の実行順序とは逆である.