看看这段代码:
template <typename K,typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return new BinaryTreeIterator(this,BinaryTreeIterator::Position::atBeginning);
}
当我尝试使用VSTS 2008编译它时,我得到:
error C2244: 'BinaryTree<K,T>::GetBeginning' : unable to match function definition to an existing declaration
see declaration of 'BinaryTree<K,T>::GetBeginning'
2> definition
2> 'Pointer<Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning(void) const'
2> existing declarations
2> 'Pointer<Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning(void) const'
宣言:
Pointer<Iterator> GetBeginning() const;
在课堂内。 BinaryTree间接继承自Collection,而BinaryTreeIterator间接继承自Iterator,它们各自容器的嵌套类。
您可以很容易地看到,即使在错误报告中,定义和声明都是相同的。这里真的有问题吗?
我发现微软发布了hotfix:“某些模板代码无法编译,安装Visual Studio 2005 Service Pack 1后出现错误C2244”。但是我找不到VSTS 2008的任何参考。
首先,我想检查一下是否有人能够在代码中发现真正的错误,如果是VS的错误,是否有人知道上述修补程序是否是解决方案并且与2008年相关。
答案 0 :(得分:2)
对于那些感兴趣的人,我尝试写一个简单的样本来重现这个问题:
template <typename T>
struct Pointer {};
template <typename T>
struct Collection {
struct Iterator {};
};
template <typename K,typename T>
struct BinaryTree : Collection<T>{
Pointer<typename Collection<T>::Iterator> GetBeginning() const;
struct BinaryTreeIterator : Collection<T>::Iterator {
template <typename X>
BinaryTreeIterator(BinaryTreeIterator*, X) {}
struct Position {
static int atBeginning() { return 0; }
};
};
};
template <typename K,typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return Pointer<typename Collection<T>::Iterator>();
}
int main(){
BinaryTree<int, float> bt;
bt.GetBeginning();
}
是的,我也得到了错误。在我们看到的代码中我看不到任何明显的错误,但是再一次,这个例子比一年中大多数理智的C ++程序员使用了更多的嵌套类和继承,所以我不能肯定地说您的代码是否正确。
此外,我不得不猜到要把它拼凑起来。 (开始时应该是什么?实际的类接口是什么?)
但我怀疑如果你没有继承其他所有东西,它会更好地工作(并且更易读,更容易调试)。
<强>更新强> 我尝试用GCC和Comeau的在线编译器编译上面的内容,并且都接受了它。所以它似乎可能是一个编译器错误。
答案 1 :(得分:1)
您可能考虑的显而易见的解决方案是在类定义中定义函数,而不是稍后重新定义它。
另外,将iterator类型放在typedef中,如下所示:
template <typename T>
struct Pointer {};
template <typename T>
struct Collection {
struct Iterator {};
};
template <typename K,typename T>
struct BinaryTree : Collection<T>{
typedef typename Collection<T>::Iterator Iter;
Pointer<Iter> GetBeginning() const;
struct BinaryTreeIterator : Collection<T>::Iterator {
};
};
template <typename K,typename T>
Pointer<typename BinaryTree<K,T>::Iter> BinaryTree<K,T>::GetBeginning() const
{
return new BinaryTreeIterator(this,BinaryTreeIterator::Position::atBeginning);
}
int main(){
BinaryTree<int, float> bt;
bt.GetBeginning();
}
似乎解决了这个问题。 不知道为什么,可能是一个错误......
答案 2 :(得分:0)
如果你把它改成这个就会编译:
template <typename K,typename T>
struct BinaryTree : Collection<T> {
Pointer<typename BinaryTree<K,T>::Iterator> GetBeginning() const;
};
template <typename K,typename T>
Pointer<typename BinaryTree<K,T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return Pointer<BinaryTree<K,T>::Iterator>();
}
一般来说,原始代码不是很正确,因为它意味着GetBeginning()可以返回任何集合,而(我假设)它只能返回二叉树集合。
编辑:
经过一番挖掘后,VC ++似乎无法处理注入良好的类名。也就是说,如果从方法声明中删除Collection :: Iterator,原始代码将被编译:
template <typename K, typename T>
struct BinaryTree : Collection<T> {
Pointer<typename Collection::Iterator> GetBeginning() const;
};
template <typename K, typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
return Pointer<Collection<T>::Iterator>();
}