C++汎用プログラミングとテンプレート

3906 ワード

目次
一.汎用プログラミング
二.関数テンプレート
2.1関数テンプレート形式
2.2関数テンプレートの原理
2.3関数テンプレートのインスタンス化
2.4テンプレートパラメータの整合原則
一時変数、参照パラメータ、constについてのブログ
三.クラステンプレート
3.1クラステンプレートの定義形式
3.2クラステンプレートのインスタンス化
一.汎用プログラミング
同じ関数を使用して異なるパラメータタイプを処理する場合、関数リロードを使用してこの機能を実現できます.
関数のリロードは便利ですが、関数のリロードにも悪い点がある可能性があります.
  • リロード関数はタイプが異なるだけで、コードの多重化率は比較的低く、新しいタイプが現れる限り、対応する関数
  • を増やす必要がある.
  • コードの保守性は比較的低く、1つのエラーですべてのリロードエラーが発生する可能性があります
  • 関数のリロードにいくつかの欠点がある以上、修正する方法はありませんか.先輩たちはこの問題を解決したに違いありません.この時、汎用プログラミングがあります.
    汎用プログラミング:タイプに関係のない汎用コードを記述することは、コード多重化の手段である.テンプレートは汎用プログラミングの基礎です.
    二.関数テンプレート
    関数テンプレートは、タイプに関係なくパラメータ化され、実パラメータタイプに基づいて関数の特定のタイプバージョンを生成する関数ファミリーを表します.
    2.1関数テンプレート形式
    template
    戻り値タイプ関数名(パラメータリスト){}
    template
    T Add(T s1, T s2)
    {
    	return s1 + s2;
    }

    注意:typenameはテンプレートパラメータを定義するためのキーワードであり、classを使用することもできます(classの代わりにstructを使用することはできません)
    2.2関数テンプレートの原理
    テンプレートは青写真で、それ自体が関数ではないことを覚えておいてください.コンパイラがこのテンプレートを使用して特定のタイプの関数を生成します.テンプレートとは、私たちがやるべきことをコンパイラに繰り返すことです.
    コンパイルフェーズでは、コンパイラは、入力された実パラメータタイプに基づいて、呼び出しのために対応するタイプの関数をプッシュします.
    例:
    template
    void Swap(T& s1, T& s2)//      
    {
    	T tmp = s1;
    	s1 = s2;
    	s2 = tmp;
    }

    このとき、呼び出し関数が入力されたパラメータが2つのintタイプのデータである場合、コンパイラはintタイプの交換関数をプッシュします.
    int s1 = 1;
    int s2 = 2;
    Swap(s1,s2);

    呼び出し関数が2つのdoubleタイプのデータである場合、コンパイラはdoubleタイプの交換関数をプッシュします.
    double s3 = 1.01;
    double s4 = 2.02;
    Swap(s3,s4);

    もちろんcharタイプも可能です.呼び出された関数が異なります
    2.3関数テンプレートのインスタンス化
    異なるタイプのパラメータで関数テンプレートを使用する場合、関数テンプレートのインスタンス化と呼ばれます.
    ①暗黙的なインスタンス化:コンパイラにテンプレートパラメータの実際のタイプを実参に基づいて推論させる
    template
    T Add(T s1, T s2)
    {
    	return s1 + s2;
    }
    void TestAdd()
    {
        int s1 = 1; 
        int s2 = 2;
        double s3 = 1.01;
        double s4 = 2.02;
        Add(s1, s2);
        Add(s1, (int)s3);//      	
    }

    しかし、伝達されるパラメータがintタイプ、doubleタイプであれば、偽入の2つのパラメータのタイプが異なる場合、コンパイラはどのように処理しますか?このような場合、コンパイラは、Tが1つしかないため、Tをintにプッシュしたり、Tをdoubleにプッシュしたりしているとは確信できないため、エラーを報告します.
    テンプレートでは、コンパイラは一般的にタイプ変換操作を行いません.変換に問題が発生すると、コンパイラは鍋を背負います.
    上記の問題を解決するには、次の2つの方法があります.
  • ユーザ自身がタイプ変換
  • を強制する.
  • 明示的インスタンス化
  • を使用
    ②明示的なインスタンス化:関数名の後の<>にテンプレートパラメータの実際のタイプを指定し、関数の戻り値は推論に参加できず、形パラメータのみ
    Add(s1, s3);

    タイプが一致しない場合、コンパイラは暗黙的なタイプ変換を試み、変換に成功しない場合、コンパイラはエラーを報告します.
    2.4テンプレートパラメータの整合原則
  • 非テンプレート関数は、同じ名前の関数テンプレートと同時に存在することができ、この非テンプレート関数
  • としてインスタンス化することもできる.
  • 非親関数および同名関数テンプレートの場合、他の条件が同じである場合、テンプレートからインスタンスを生成することなく、異動時に非テンプレート関数が優先的に呼び出されます.テンプレートがよりよく一致する関数を生成できる場合は、テンプレートを選択します.
  • int Add(int s1, int s2)
    {
    	return s1 + s2;
    }
    
    template
    T1 Add(T1 s1, T2 s2)
    {
    	return s1 + s2;
    }
    void TestAdd()
    {
    	int s1 = 1; 
    	int s2 = 2;
    	double s3 = 1.01;
    	double s4 = 2.02;
    	
            Add(s1, s2);//       	
            Add(s1,s2);//    
    	Add(s1, s4);//    
            Add(s3, s4);//    
    }
    	
    
    

    一時変数、参照パラメータ、constについてのブログ
    https://blog.csdn.net/qq_41209741/article/details/84255449
    三.クラステンプレート
    3.1クラステンプレートの定義形式
    template
    class     
    {
        //      
    };

    3.2クラステンプレートのインスタンス化
    クラステンプレートのインスタンス化には、クラステンプレート名の後に<>を付け、インスタンス化のタイプを<>に配置する必要があります.クラステンプレート名は真のクラスではなく、インスタンス化の結果こそ真のクラスです.
    メンバー変数がプライベートで直接アクセスできないため、自己実装のシーケンステーブルにアクセスできます.関数Print、リロード入力および出力、リロード[]を提供できます.
    T& operator[](size_t pos)
    {
        return _a[pos];
    }
    
    size_t Size()
    {
        return _size;
    }

    クラステンプレートメンバー関数の分離定義:
    Vector();
    .
    .
    .
    
    template
    Vector::Vector()
        :_a(nuulptr)
        ,_capacity(0)
        ,_size(0)
    {}

    テンプレートクラス名:Date Vector
    テンプレートクラスタイプ:Date Vector