1.3つの継承されたアクセス許可
- public:クラスの内外からアクセスできます。
protected
:クラスおよびサブクラス内にアクセスしますが、クラス外にはアクセスしません。- private:クラス内のアクセスのみが許可され、サブクラスにもクラス外にもアクセスできません。
2.継承権限を調整します
using class name ::変数名またはメソッドを使用して、単一のメンバーまたはメソッドの継承権限を制御できます。使用方法は次のとおりです。SonがFatherを継承すると、Fatherクラスのキー権限が公開に変更され、外部からもアクセスできるようになります。Sonクラスのプライベートに配置すると、キーはプライベートになります。 Sonに送信され、Sonは使用できなくなります。サブクラスによって継承されます。
class Father
{
protected key;
};
class Son :public Father
{
public:
using Father::key;
}
3.継承タイプ
継承タイプには9つの組み合わせがあります。原則は、プライベート+保護などの最小特権の原則であり、継承された特権はプライベートのいずれか小さい方になります。
[外部リンクの画像転送に失敗しました。ソースサイトにアンチホットリンクメカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします(img-IkbpsDgh-1611509116567)(C:\ Users \ 85114 \ AppData \ Roaming \ Typora \ typora-user-images \ image-20210121222038995.png)]
4.多重継承
SofaBedがSofaとBedを同時に継承するなど、クラスは複数の基本クラスから同時に継承できます。
class SofaBed : public Sofa, public Bed
{
}
5.仮想継承
多重継承の場合、継承される可能性のある複数の基本クラスは同じメンバーまたはメソッドを持ち、この時点であいまいさが発生します。仮想継承は、あいまいさの問題を解決し、メモリの浪費の問題も解決できます(同じメンバーまたはメソッドのコピーが1つだけ保持されます)。仮想継承により、4バイトのオフセットポインタが追加されます。これは、Baiduがメモリ分散を継承するために使用できます。
class SofaBed : virtual public Sofa, virtual public Bed
{
}
仮想継承コンストラクタとデストラクタの呼び出しシーケンス:
- 仮想基本クラスのコンストラクターが最初に実行され、複数の仮想基本クラスのコンストラクターが継承された順序で構築されます。
- 基本クラスのコンストラクターを実行すると、複数の基本クラスのコンストラクターが継承順に作成されます。
- メンバーオブジェクトのコンストラクターが実行され、複数のメンバーオブジェクトのコンストラクターが指定された順序で構築されます。
- 派生クラスのコンストラクターを実行します。
- 破壊は、構築の逆の順序で実行されます。
6.サブクラスはパラメーターを基本クラスコンストラクターに渡します
サブクラスは、基本クラス(入力パラメーター)およびメンバークラス名(入力パラメーター)の形式で、コンストラクター内の基本クラスコンストラクターにパラメーターを直接渡すことができます。これらのコンストラクターの呼び出し順序は、書き込みの順序とは関係ありません。最初の呼び出しに従って、セクション5で説明されている順序で呼び出されます。
class SofaBed : virtual public Sofa, virtual public Bed
{
private:
Data data; /* Data类 */
public:
/* SofaBed构造函数 */
SofaBed(char *str1, char*str2, char *str3, char* str4) : Sofa(str1), Bed(str2), data(str3)
{
}
}
7、ポリモーフィズムの実現
ポリモーフィズムは、実現するために仮想関数に依存する必要があります。
#include <iostream>
using namespace std;
class Human {
private:
int a;
public:
virtual void eat(void) {cout<<"use hand to eat"<<endl;}
};
class English:public Human{
public:
void eat(void){cout<<"use knife to eat"<<endl;}
};
class Chinese:public Human{
public:
void eat(void){cout<<"use chopsticks to eat"<<endl;}
};
void eatTest(Human &human)
{
human.eat();
}
int main(int argc, char **argv)
{
Human h;
English e;
Chinese c;
eatTest(h);
eatTest(e);
eatTest(c);
}
実行結果は以下のとおりです。
use hand to eat
use knife to eat
use chopsticks to eat
Humanクラスのeatメソッドの仮想属性を削除するか、void eatTest(Human&human)関数をvoid eatTest(Human human)に変更すると、呼び出しの結果は次のようになり、ポリモーフィズムを実現できなくなります。ポリモーフィズムは、ポインターまたは参照を介してのみ実現でき、値を直接渡すことはできません。
use hand to eat
use hand to eat
use hand to eat
8.ポリモーフィズムの原理
プログラムは静的バインディングと動的バインディングに分けられます。静的バインディングの場合、呼び出される関数はコンパイル時に決定されます。非仮想関数の場合は静的にバインドされます。動的バインディングの場合、呼び出される関数は、仮想関数など、プログラムの実行時に動的に決定されます。場合。静的バインディングは非常に効率的であり、動的バインディングはポリモーフィズムをサポートします。
クラス内の仮想関数の場合、クラス内の仮想関数テーブルへのポインターがあり、次のように、呼び出し時に仮想関数テーブル内の対応する関数が検出され、ポインターを介して呼び出されます。図。
上記の例では、sizeof(h)= sizeof(e)= sizeof(c)= 16です。仮想関数テーブルには、仮想関数ポインターだけでなく、クラスおよび継承情報の一部も含まれているためです。
9.ポリモーフィズムの限界
- クラスのメンバーのみが仮想関数として宣言できます。
- 静的メンバー関数を仮想関数にすることはできません。
- インライン関数を仮想関数にすることはできません。
- コンストラクターを仮想関数にすることはできません。
- デストラクタは通常、仮想関数として宣言されます。デストラクタが仮想関数として宣言されていない場合、サブクラスが破棄されると、親クラスのデストラクタのみが呼び出され、このクラスのデストラクタは呼び出されません。
- オーバーロードされた関数を仮想関数にすることはできません。
- 関数パラメーターが同じで、戻り値がクラスのポインターまたは参照である場合、仮想関数として宣言できます。戻り値が他のタイプの場合、仮想関数として設定することはできません。 。