0

次のコードスニペットをコンパイルしようとしています。最後に発生するエラーを確認してください。

#include "Tree.h"

template <class T>
CNode<T>* CNode<T>::GetChild(const T& kData)
{
    for( std::vector< CNode >::iterator it = m_vChildren.begin(); it!= m_vChildren.end(); ++it)
    {
        if(*it== kData)
        {
           return &(*it);
        }
    }
}

Tree.h(ヘッダーファイル):

#include "../include_m.h"
#include <vector>

template <class T>
class CNode
{
 public:
    CNode(const T& kData)
    {
        m_Data = kData;
    }

    void AddChildNode(const CNode& kcChildNode);
    void DeleteChildNode(const T& kData);
    void GetChildNode(const T& kData) const;
    void Print();

 private:
    T                       m_Data;
    std::vector<CNode>      m_vChildren;

    CNode * GetChild(const T& kData);
};

これはコンパイルに失敗し、次のエラーが発生します。

g++ -o tree Tree.cpp 
Tree.cpp: In member function ‘CNode<T>* CNode<T>::GetChild(const T&)’:
Tree.cpp:12: error: expected `;' before ‘it’
Tree.cpp:12: error: ‘it’ was not declared in this scope
4

2 に答える 2

2

足りないのはtypename前だけですstd::vector< CNode >::iteratorCNode<T>::GetChildはテンプレート化されたコンテキストであるため、コンパイラはが型または値のメンバーであるかどうかを知ることができませんstd::vector< CNode >::iterator。たとえば、クラスフィールドとして定義されているstd::vector<CNode<int> >場所を特殊化したテンプレートを作成できます。このあいまいさを解決するには、キーワードiteratorを使用する必要があります。typename

関連するメモとして、キーワードが必要なさらに難しい状況があります。templateここで言及する価値があるかもしれません。次のことを考慮してください。

template <class T>
struct C {
   template <class U>
   void memfunc();
};

template <class T>
void func() {
   C<T> c;
   c.template memfunc<int>();
}

template問題と同様の理由により、コンパイラは、メンバーが実際にクラスのすべての特殊化のテンプレートメソッドであることを認識できないため、最後の行にoddキーワードが必要ですC。これで表示されるエラーメッセージも非常に奇妙で、毎回私を困惑させます。

他の回答にも、ファイルにテンプレート定義を含めることに関する関連点があり.cppます。おそらく彼らのアドバイスに従い、定義を.hファイルに移動する必要があります。ただし、実際には、ファイルにテンプレート定義が必要な場合があり.cppます。たとえば、メソッドが同じ.cppファイルでのみ使用されている可能性があります。または、明示的なインスタンス化を使用して、テンプレート化されたメンバー関数をインスタンス化するタイプを制御したい場合があります。これは次の方法で実現できます。

template class CNode<int>; // explicitly instantiate CNode<int> 
template CNode<double>* CNode<double>::GetChild(const double& kData); // explicitly instantiate only the GetChild method for CNode<double>

このように、メソッドの実装に変更を加えるたびに.cpp含まれるすべてのファイルを再コンパイルする必要はありません。tree.hGetChild

于 2013-03-11T06:45:43.343 に答える
0
  1. .cppテンプレートクラスでファイルを使用することはできません。すべてがに含まれている必要があります.h
  2. ヘッダーでへの参照を使用してCNode、戻り値の型、std::vectors内に配置された値、およびパラメーターを示しています。これらはすべてに変更する必要がありCNode<T>ます。

これはCNode、それ自体がクラスとして存在するのではなく、コンパイル時に作成されるクラスのテンプレートとして存在するためです。内部に配置されたすべてのタイプについて<T>; コンパイル時に新しいクラスが作成されます。

意味CNode<X>はと同じクラスでCNode<Y>CNodeなく、binary/executableにはまったく存在しません。

つまり、の値を指定しないと、CNodeまたはそのメンバーを参照することはできません<T>

于 2013-03-11T06:45:08.460 に答える