テンプレート化プログラミング

4625 ワード

テンプレートの概念:
C++を最初に設計した場合、templateはパラメータ化されたタイプと呼ばれます.パラメータ化は、タイプに関する情報がtemplate定義から剥離できるためです.タイプとは、各クラステンプレートまたは関数テンプレートが、その役割またはその中に含まれるタイプによって実質的に変化することを意味します.
その後templateは一般的にテンプレートと呼ばれている.≪アクション|Actions|emdw≫:ユーザーが指定した特定のタイプまたは特定の値に基づいて、関数またはクラスを自動的に生成できます.
実装テンプレート:
学習や問題作成では、標準ライブラリが提供するテンプレートクラス(vector、stringなど)をよく使用しています.テンプレートクラスの特性を理解することができます.これは、実装において一定の参考価値があります.
説明を容易にするために、テンプレート化プログラミングを説明するために、その後、二叉木のクラステンプレートが実装される.
  • パラメータ化されたタイプ
  • 通常、ツリーを作成する場合は、2つのクラスを定義する必要があります.
    typedef int DataType;
    
    class BTNode{
    	BTNode(DataType data = 0)
    	:_data(data)
    	, _leftChild(NULL)
    	, _rightChild(NULL)
    	{}
    
    	DataType _data;
        int _count;
    	BTNode* _leftChild;
    	BTNode* _rightChild;
    };
    
    class BinaryTree{
    
    	// ...
    
    	BTNode* _root;
    };

    コードに示すように、BTNodeクラスはノードの実値を格納するために使用され、BinaryTreeクラスはルートノードへのポインタを格納するために使用される.テンプレートメカニズムがない場合、異なるタイプの数値を格納するためにプログラムコードを変更する必要があります.
    templateメカニズムは、このようなトラブルを解決するために、クラス定義の「タイプに関連」と「タイプから独立」の2つの部分を分離します.私たちがしなければならないのは、タイプに関連する部分をパラメータ化するだけです.(例えば、BTNodeクラスの_dataメンバータイプをパラメータ化することができる)
    クラスのテンプレート化:
    template 
    class BinaryTree;
    
    template 
    class BTNode{
    	
    	// ...
    
    	friend class BinaryTree;
    
    	elemType _data;
        int _count;
    	BTNode* _leftChild;
    	BTNode* _rightChild;
    };

    この定義では、elemTypeはプレースホルダとして扱われ、その名前は任意に定義できます.ユーザーが特定のタイプを指定する前に、任意のタイプのデータを指すことができます.
    BTNodeクラスは、BinaryTreeクラスオブジェクトのプロパティを格納するため、これを併用するため、BinaryTreeをBTNodeクラスの友元として宣言します.
    インスタンス化する方法は、次のとおりです.
         BTNode< int > bti;//クラステンプレート名+オブジェクト名;
    インスタンス化によりintで置換_dataは,intによって生成されたBTNodeの友元を代入する.
    ---テンプレートパラメータリストの制限はどのような場合に必要ですか?
    class templateおよびそのメンバーの定義には必要ありませんが、他の場合は限定する必要があります.
  • テンプレートの定義
  • BinaryTreeテンプレートクラスの一部の定義は、次のようになります.
    template 
    class BinaryTree{
    public:
    	BinaryTree();
    	BinaryTree(const BinaryTree&);
    	BinaryTree& operator=(const BinaryTree&);
    	
    	inline bool empty(){ return _root == 0; }
    	void clear();
    
    	~BinaryTree();
    
    private:
    	BTNode* _root;
            void copy(BTNode* tar, BTNode* src);
    };

    インライン関数のテンプレートクラスでの定義は、一般クラスの定義と同じであることがわかります.しかし、内外で定義すれば違います.
    template 
    inline bool BinaryTree::empty()
    {
    	return _root == 0;
    }

    キーワードtemplateとパラメータリストの後にinlineを付け,その後関数戻り値タイプを付け,内外で定義するためインライン関数名の前に役割ドメイン限定を付けることがわかる.
    他のメンバー関数も実装されます.
    //     
    template 
    inline BinaryTree::BinaryTree()
    	:_root(0)
    {}
    
    //     
    template 
    inline BinaryTree::BinaryTree(const BinaryTree& rhs)
    {
    	copy(_root, rhs._root);
    }
    
    //        
    template 
    inline BinaryTree& BinaryTree::operator=(const BinaryTree& rhs)
    {
    	if (this != &rhs){
    		clear();
    		copy(_root, rhs._root);
    	}
    	return *this;
    }
    
    //     
    template 
    inline BinaryTree::~BinaryTree()
    {
    	clear();
    }
  • テンプレートタイプパラメータ処理
  •         1. パラメータの伝達方法?
  • 組み込み型パラメータの処理時には、パラメータ伝達
  • が値伝達で行う.
       void func(int val);
  • カスタムタイプのパラメータを処理する際には、参照を伝達するように伝達することが多い(値伝達も可能であるが、オーバーヘッドが大きい)
  • .
       void func(const custom& val);
  • は、組み込みタイプでもカスタムタイプでもクラステンプレートの実際のタイプとして指定できます.by referenceで処理することをお勧めします.

  •           2. コンストラクション関数定義で、パラメータの初期化をどのように選択しますか?
  • 初期化リスト:
  • template 
    inline BTNode::BTNode(const valType& data)
        :_data(data)
    {
        _count = 1;
        _rightChild = _leftChild = 0;
    }
  • 構造関数内:
  • template 
    inline BTNode::BTNode(const valType& data)
    {
        _data = data;
        _count = 1;
        _rightChild = _leftChild = 0;
    }

    比較的推奨されるのは、最初の初期化方式です.効率が高いからです.
  • 定数式をパラメータ
  • とする
    データ型はテンプレートパラメータとして使用できるほか、定数式をパラメータとして使用することもできます.
  • 例えば、1つの数列をテンプレート化する:
  • template 
    class num_sequence{...};

    テンプレート関数のパラメータリストの場所にデフォルト値を指定することもできます.
    template 
    class num_sequence{...};
  • グローバル役割ドメインの下の関数およびオブジェクトは、そのアドレスも定数式であるため、パラメータとして使用することもできる.
  • template 
    class num_sequence{...}