我正在尝试编译以下代码片段。请检查我最后得到的错误。
#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
答案 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)
.cpp
文件与模板类一起使用。一切都必须在.h
。CNode
的引用来指示返回类型,std::vector
内的值和参数。这些所有必须更改为CNode<T>
。这是因为CNode
本身不是一个类,而是一个模板,用于在编译时创建的类。对于放置在<T>
内的每种类型;在编译时创建一个新类。
含义CNode<X>
与CNode<Y>
不是同一个类,而CNode
在二进制/可执行文件中根本不存在。
这意味着您可以从不引用CNode或其成员,而无需为<T>
提供值。