C++ノット:マルチステート(2)--カテゴリと実装、ダイナミックマルチステート

8791 ワード

マルチステート
1、動的多態の実現原理
2、多態の分類と実現方法
3、動的多態の四つの状況
(2)マルチステートのカテゴリと実現方法
2.1静的マルチステート:コンパイル時のマルチステート、関数のマルチステート、リロード、テンプレート、マクロ
2.2動的マルチステート:実行時マルチステート、クラスのマルチステート、継承と虚関数、晩バインド、動的バインド
2.3パッケージはコードをモジュール化し、既存のコードを拡張することができ、彼らの目的はすべてコードの再利用である.マルチステートの目的はインタフェースの再利用です.すなわち,どのクラスのオブジェクトが渡されても,関数は同じインタフェースを介してそれぞれのオブジェクトに適応する実装方法を呼び出すことができる.
(3)動的多態の4つのケース
3.1親のポインタでサブクラスオブジェクトを指す
3.2親クラスのポインタを関数のパラメータとして使用し、このポインタを使用して任意のサブクラスオブジェクトにも彼自身を含めることができます.
3.3複合クラスでは、クラスのメンバー変数として高レベルのクラス(親のポインタ)をできるだけ飲むことで、対応するサブクラスオブジェクトを作成できます.
3.4コンテナで、親ポインタのコンテナを宣言できます.この場合、対応する子オブジェクトをコンテナに追加できます.
ダイナミックマルチステートと静的マルチステートの比較
せいてきたじゅうたい
メリット:
静多状態はコンパイル期間中に完了するため、効率が高く、コンパイラも最適化することができる.
強い適合性と緩和結合性があり、例えば偏特化、全特化によって特殊なタイプを処理することができる.
最も重要な点は,テンプレートプログラミングによりC++に汎用設計の概念,例えば強力なSTLライブラリをもたらす静的多態である.
欠点:
テンプレートは静的マルチステートを実現するためのテンプレートであるため、テンプレートの不足は、デバッグ困難、コンパイル時間、コード膨張、コンパイラサポートの互換性などの静的マルチステートの劣勢である.
異質オブジェクトの集合を扱うことができない
ダイナミックマルチステート
メリット:
OO設計は、客観世界であるという直感的な認識である.
インタフェースからの分離、多重化を実現
同じ継承システムの下で異質オブジェクトの集合を処理する強力な威力
欠点:
実行期間バインドは、ある程度の実行時オーバーヘッドを引き起こす.
コンパイラは虚関数を最適化できません
重いクラス継承システムは、インタフェースの修正にクラス階層全体に影響します.
相違点:
本質は異なり、静的多態はコンパイル期間で決定され、テンプレートによって現完成され、動的多態は運行期間で決定され、継承、虚関数によって実現される.
ダイナミックマルチステートインタフェースは明示的で、関数署名を中心とし、マルチステートは虚関数によって実行期間で実現され、静的マルチステージインタフェースは暗黙的であり、有効な式を中心とし、マルチステートはテンプレートによって現在のコンパイル期間で完成する.
同じ点:
いずれも多態性、静的多態/コンパイル期間多態、動的多態/運転期間多態を実現することができる.
いずれもインタフェースと実装を分離することができ、1つはテンプレート定義インタフェース、タイプパラメータ定義実装、1つはベースクラス虚関数定義インタフェースであり、継承クラスが実装を担当する
;
//ここで「非表示」は、生クラスを割り当てる関数が、その同名のベースクラス関数をマスクしているものです.ルールは次のとおりです.
//(1)派生クラスの関数がベースクラスの関数と同名であるがパラメータが異なる場合.この場合、virtualキーワードの有無にかかわらず、ベースクラスの関数は非表示になります(リロードと混同しないように注意).
//(2)派生クラスの関数がベースクラスの関数と同名でパラメータも同じであるが、ベースクラスの関数にvirtualキーワードがない場合.このとき、ベースクラスの関数は非表示になります(オーバーライドと混同しないように注意).
//上記の手順:
//(1)関数Derived::f 1(float)はBase::f 1(float)を上書きします.
//(2)関数Derived::f 2(int)は、再ロードではなくBase::f 2(float)を非表示にします.
//(3)関数Derived::f 3(float)はBase::f 3(float)を隠し、上書きではなく
A、動的多態
#ifndef __C__No807Class__Father__
#define __C__No807Class__Father__

#include 
using namespace std;
class Father
{
public:
    virtual void print();
};
#endif /* defined(__C__No807Class__Father__) */

#include "Father.h"
void Father::print()
{
    cout << "Father print" << endl;
}

#ifndef __C__No807Class__Son__
#define __C__No807Class__Son__

#include 
#include "Father.h"
class Son : public Father
{
public:
    void print();
};
#endif /* defined(__C__No807Class__Son__) */

#include "Son.h"
void Son::print()
{
    cout << "Son print" << endl;
}

#ifndef __C__No807Class__Son2__
#define __C__No807Class__Son2__

#include 
#include "Father.h"
class Son2 : public Father
{
public:
    void print();
};

#endif /* defined(__C__No807Class__Son2__) */

#include "Son2.h"
void Son2::print()
{
    cout << "Son2 print" << endl;
}
#include 
#include
#include
#include "Son.h"
#include "Son2.h"
//               ,                 
void func(const vector&V)  //   ,             ,                          
{
    for(int i = 0; i < V.size(); ++i)
    {
        V.at(i) -> print();
    }
}
void foo(Father &f)  //         ,                        
{
    f.print();  //Son,    Father
}

int main()
{
    Son s;
    Son2 s2;
    Father f;
    Father *p;
    p = &s;    //          
    p -> print();
    p = &s2;
    p -> print();
    foo(s);
    vectorFatherVector;
    FatherVector.push_back(&s);
    FatherVector.push_back(&s2);
    FatherVector.push_back(&f);
    func(FatherVector);  
    return 0;
}

B、静的マルチステート--リロード
関数のリロードは、同じ関数名を使用しますが、関数パラメータのリストが異なり、(パラメータタイプまたは個数)、この方法でマルチステートを実現します.関数のリロードとテンプレートは多態的には同じで、リロード関数が複数の関数を書くだけで、テンプレートではtypedefを使って、関数を1つ書けば、呼び出すときにパラメータのタイプに応じて自分でマッチングを置き換えるだけです.
#include 
#include 
using namespace std;
int add (int num1, int num2)
{
    return (num1 + num2);
}
int add (int num1, string str1)
{
    return (num1 + atoi(str1.c_str()));  //               
}
int add (int num1, char c1)
{
    return (num1 + c1);
}
int main()
{
    int n1 = 10, n2 = 20;
    string s1 = "30";
    char c1 = 'a';
    cout << n1 << " + " << n2 << " = " << add(n1, n2) <

C、静的マルチステート--テンプレート
template 
T max(const T& i, const T& j) 
{
       return (i > j) ? i : j;
}
//              (  ),          >       ,      bool  。
  :
int a = 3; int b = 4;
cout << max(a, b) << endl;
float c = 2.4; float d = 1.2;
cout << max(c, d) << endl;
     :
         4
        2.4
          ,                  ,             max(a, b)          
int max(const int& i, const int& j) 
{
       return (i > j) ? i : j;
}
     T   int;
    max(c, d)          
float max(const float& i, const float& j)
{
        return (i > j) ? i : j;
}
テンプレート2
#include
#include
#include
using namespace std;
/*     */
class Base
{
public:
    virtual void print()=0;
};

class Child1:public Base
{
    void print()
    {
        cout<&V)
{
    for(int i=0;iprint();
    }
}

/*    ,    */
template
void TempalteFuncion(const vector&V)
{
    for(int i=0;iprint();
    }
}
int main()
{
    /*             */
    Child1 child1;
    Child2 child2;
    Base *p;
    p=&child1;
    p->print();
    p=&child2;
    p->print();
    vectorBaseVector;
    BaseVector.push_back(&child1);
    BaseVector.push_back(&child2);
    func(BaseVector);
    TempalteFuncion(BaseVector);
    
    return 0;
}

D、静的マルチステート--マクロマルチステート(無視)
#include  
#include  
using namespace std;  
  
#define ADD(A,B) ((A)+(B))  
  
void main()  
{  
    /*   */  
    int num1=10;  
    int num2=20;  
    string str1="22";  
    string str2="33";  
    cout<

E、サブクラスポインタが親オブジェクトを指す、非表示
#include 
using namespace std;
class A
{
public:
    void f1()
    {
        cout << "1" << endl;
    }
    virtual void f2()
    {
        cout << "2" << endl;
    }
};
class B : public A
{
public:
    void f1()
    {
        cout << "3" << endl;
    }
    void f2()
    {
        cout << "4" << endl;
    }
};
int main()
{
    A a;
    B b;
    A *p = &a;
    p -> f1();  //1
    p -> f2();  //2
    p = &b;
    p -> f1();  //1
    p -> f2();  //4
    B *ptr = (B *)&a;  //    ptr,    a        B     
    ptr -> f1();  //3
    ptr -> f2();  //2
    
    return 0;
}
#include 
using namespace std;
class Base
{
public:
    virtual void f1(float x)
    {
        cout << "Base f1 (float) = " << x << endl;
    }
    void f2(float x)
    {
        cout << "Base f2 (float) = " << x << endl;
        }
    void f3(float x)
    {
        cout << "Base f3 (float) = " << x << endl;
    }
};
class Derived : public Base
{
public:
    void f1(float x)
    {
        cout << "Derived f1 (float) = " << x << endl;  //  ,  
    }
    void f2(int x)
    {
        cout << "Derived f2 (float) = " << x << endl;  //  
    }
    void f3(float x)
    {
        cout << "Derived f3 (float) = " << x << endl;  //  
    }
};
int main()
{
    Derived d;
    Base *pb = &d;
    Derived *pd = &d;
    
    pb -> f1(3.14f);  //D f1
    pd -> f1(3.14f);  //D f1
    
    pb -> f2(3.14f);  //B f2
    pd -> f2(3.14f);  //D f2
    
    pb -> f3(3.14f);  //B f3
    pd -> f3(3.14f);  //D f3
    
    return 0;
}
//  “  ”                    ,    :
//(1)                ,      。  ,    virtual    ,         (        )。
//(2)                ,       ,        virtual    。  ,        (        )。
//      :
//(1)  Derived::f1(float)   Base::f1(float)。
//(2)  Derived::f2(int)   Base::f2(float),     。
//(3)  Derived::f3(float)   Base::f3(float),