20170326_C++多態の意味を言ってください


20170326_C++多態の意味を言ってください
1、多態とは何ですか.
(1)同じベースクラスを継承することにより,関連する異なる派生クラスが生成され,ベースクラスと同名のメンバー関数は異なる派生クラスで異なる実装,すなわち,1つのインタフェース,複数のメソッドがある.
(2)多態は対象に向かう重要な技術の一つであり,行為のパッケージであり,同じ事物が表現する多様な形態であり,簡単に言えば,一つのインタフェース,多様な形態である.
(3)では、問題が発生しました.現在、実行時に同じメンバー名を使用してクラスオブジェクトのメンバー関数を呼び出すと、どのオブジェクトのメンバー関数が呼び出されますか.これがマルチステートで解決すべき問題です.
2、多態の作用?
(1)マルチステート技術により、ベースクラスポインタまたはベースクラス参照を派生クラスオブジェクトに向けることができる.
(2)異なる派生クラスのオブジェクトをすべてベースクラスオブジェクトとして扱うことで,異なる派生クラス間の差異を遮断し,需要の絶え間ない変化に適応するために汎用的なコードを書くことができる.
3、多態の分類?
(1)多態は二つに分けられる.
  • は静的マルチステートであり、コンパイル時のマルチステートを指し、関数リロードまたは演算子リロードによって実現される.
  • は動的多態であり、実行時の多態を指し、虚関数とベースクラスポインタの共同作用によって実現される.

  • 4、C++でどのように多態を実現しますか?
    (1)C++では、ベースクラスポインタはベースクラスオブジェクトを指すために使用され、これを使用して派生クラスオブジェクトを指す場合はポインタタイプ変換(アップリンク変換)を行い、派生クラスポインタをベースクラスポインタに変換するので、このポインタは派生クラスオブジェクトのベースクラス部分を指し、このポインタでは派生クラスオブジェクトのメンバー関数を呼び出すことはできません.
    しかし,虚関数はこの制限を突破した.派生クラスのベースクラス部分では、派生クラスの虚関数がベースクラスの元の同名虚関数に取って代わるため、ベースクラスポインタを派生クラスオブジェクトに向けた後、このベースクラスポインタを使用してこの同名虚関数メンバーを呼び出すと、派生クラスの虚関数が呼び出されます.
    (2)基底クラスのあるメンバ関数を虚関数として宣言すると、C++は、その派生クラスにおいてその虚関数を再定義して新しい機能を付与し、基底クラスポインタが同じクラスの異なる派生クラスのオブジェクトを指すことで、対応する派生クラスの同名虚関数を呼び出すことができる.
    虚関数によって実現される動的多様性は、同じクラスの異なる派生クラスオブジェクトが、同じ関数呼び出しに対して異なる応答を行うことである.
    (3)虚関数の使用方法は以下の通りである.
  • ベースクラスでvirtualキーワードを使用してメンバー関数を虚関数として宣言します(これにより、派生クラスで虚関数を再定義し、新しい機能を付与できます).
  • 派生クラスでこの虚関数を再定義します.この虚関数は、関数名、パラメータリスト、戻り値タイプがベースクラスの虚関数と同じであり、必要に応じてその関数体を再定義する必要があります.

  • (4)C++は,1つのメンバ関数が虚関数として定義されると,その派生クラスの同名関数は自動的に虚関数となる(キーワードvirtual表示宣言は必ずしも必要ない)が,明瞭にするために各層にvirtualキーワードを付けることに慣れている.
    例を次に示します.
    class base
    {
      public:
        base(int a):b(a){}
        void my()
            { cout<func();//  2:    child1  func()
    c1.func();//
    bptr->my();//
    c1.my();//
    
    bptr=&c2;//  3:           child2
    bptr->func();//  4:    child2  func()
    c2.func();//
    
    bptr->my();//
    
    c2.my();//
    

    5、虚関数と純虚関数の違いと関連?(1)メンバー関数の呼び出しは、オブジェクト名またはベースクラスポインタまたはベースクラス参照によってアクセスされるかを考慮する必要があります.後者の場合は、ダミー関数として宣言する必要があります.
    (2)虚関数:クラスに虚関数virtualが定義されている場合、この虚関数は実装され、その役割は、このクラスの派生クラスで虚関数が上書きされ、異なる機能として実装され、ベースクラスポインタと組み合わせて動的多様性を実現することである.
    (3)純虚関数:時には、虚関数を定義する際に、その関数体を定義しないことがある.すなわち、その関数体は空であり、その役割は虚関数名を保持するだけであり、インタフェースの統一性に注目し、その具体的な機能はその派生クラスによって実現される.例えば、virtual float area(float a,float b)=0;
  • の最後尾の"=0"の役割は、コンパイラに純粋な虚関数であることを伝えるだけです.
  • 純虚関数は関数の名前のみを有し、関数体がなく、関数の機能を備えていないため呼び出されない.関数の機能は、派生クラスで再定義された後にのみ呼び出されます.
  • 純虚関数が1つのクラスに宣言されているが、その派生クラスにおいて純虚関数が定義されていない場合、この虚関数はこの派生クラスにおいて依然として純虚関数であり、関数の機能を備えていない.

  • (4)抽象クラスと抽象ベースクラス:オブジェクトを定義せずに継承されたクラスとして1つの基本タイプとしてのみ使用され、抽象クラスと呼ばれる.ベースクラスとしてよく使用されるため、抽象ベースクラスとも呼ばれる.純粋な虚関数を含むクラスは、すべて抽象クラスであり、このクラスはオブジェクトを直接生成することはできない(例)その役割は、クラスファミリーの共通のベースクラスとして、またはクラスファミリーに共通のインタフェースを提供することである.
    (5)虚関数を使用する場合、システムには一定の空間オーバーヘッドが必要である.クラスに虚関数が含まれている場合、コンパイルシステムは虚関数ポインタvptr(4バイト)を構築するとともに、この虚関数ポインタは虚関数テーブルvtableを指し、虚関数テーブルはポインタ配列であり、クラス内の各虚関数のエントリアドレスが格納される.(ルックアップテーブルは効率的なので、マルチステート性は効率的です.)
    6、虚析构関数の役割?
    (1)派生クラスのオブジェクトがメモリから取り消されると、派生クラスの解析関数を呼び出してそのオブジェクトの派生クラス部分を解放し、ベースクラスの解析関数を呼び出してそのオブジェクトのベースクラス部分を解放することで、オブジェクトのメモリを完全に解放することができる.
    (2)ただし、ベースクラスポインタで派生クラスオブジェクト、すなわちbase*bptr=new childを指す場合、delete bptr;でbptrが指す動的記憶空間を取り消す場合、ベースクラスの解析関数のみを実行してそのスタックメモリのベースクラス部分を解放するが、派生クラスの解析関数を実行してそのスタックメモリの派生クラス部分を解放することはない.この場合、メモリ漏洩現象になる.
    (3)このような現象を回避するために、ベースクラスの構造関数を虚構造関数として宣言することで、上記の問題を解決した(すなわち、派生クラスの構造関数を呼び出して動的空間の派生クラス部分を解放し、ベースクラスの構造関数を呼び出してその動的空間のベースクラス部分を解放し、スタックメモリを完全に解放することができる).
    (4)ベースクラスの構造関数を虚構造関数として宣言すると,そのベースクラスのすべての派生クラスの構造関数が自動的に虚構造関数となる.
    7、クラスのメンバー関数のリロード、上書き(書き換え)、非表示(再定義)の違いと関連付け?
    答え:関数のリロード、関数のオーバーライド、関数の非表示の概念と特徴を簡単に説明します.
    関数リロード:リロード関数は、通常、機能が似ている関数のセットに名前を付けるために使用されます.
    (1)2つの関数が同じクラスドメインにあること
    (2)両関数の名前が同じ
    (3)2つの関数のパラメータリストが異なる必要がある
    ≪関数オーバーライド|Function Override|emdw≫:オーバーライドは、生クラス関数をベースクラス関数にオーバーライドするように割り当てられます.
    (1)2つの関数を異なるクラスドメインに配置する
    (2)両関数の名前が同じ
    (3)ベースクラス関数は虚関数でなければならない
    (4)2つの関数のパラメータリストと戻り値タイプが同じである
    ≪関数の非表示|Function Hide|oem_src≫:生クラスを割り当てる関数は、同じ名前のベースクラス関数をマスクします.
    (1)2つの関数が異なるクラスドメインにある
    (2)両関数の名前が同じ
    (3)2つの関数のパラメータリストが異なる
    (4)派生クラス関数がベースクラス関数のパラメータリストと同じであるが、ベースクラス関数にvirtualキーワードがない場合、関数非表示も発生する