以下代码有什么问题

时间:2013-03-11 06:19:32

标签: c++

我正在尝试编译以下代码片段。请检查我最后得到的错误。

#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

3 个答案:

答案 0 :(得分:2)

typename之前,您所遗漏的只是std::vector< CNode >::iterator。由于CNode<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关键字,因为由于类似的原因导致问题,编译器无法知道该成员实际上是该类的所有特化中的模板方法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.h的每个GetChild文件。

答案 1 :(得分:0)

将所有实施放在.h内,在typename之前使用std::vector< CNode >::iterator

for(typename std::vector< CNode >::iterator it = m_vChildren.begin(); ...

答案 2 :(得分:0)

  1. 您不能将.cpp文件与模板类一起使用。一切都必须在.h
  2. 您在标头中使用对CNode的引用来指示返回类型,std::vector内的值和参数。这些所有必须更改为CNode<T>

  3. 这是因为CNode本身不是一个类,而是一个模板,用于在编译时创建的类。对于放置在<T>内的每种类型;在编译时创建一个新类。

    含义CNode<X>CNode<Y>不是同一个类,而CNode在二进制/可执行文件中根本不存在。

    这意味着您可以从不引用CNode或其成员,而无需为<T>提供值。