我遇到了模板类和继承问题,我无法弄清楚。 这是使用过的课程。
带有typedef的接口模板类:
template < const unsigned long Number >
class IA
{
protected:
typedef TemplateVector<Item*, Number > List; //template array
public:
virtual List* getList() = 0;
};
具有相同typedef(.hpp)的真实类:
template < unsigned long Number >
class A : public IA< Number >
{
typedef typename IA< Number >::List List;
public:
virtual List* getList();
private:
List* m_list;
};
#include "A.cpp"
具有相同typedef(.cpp)的真实类:
template < unsigned long Number >
TemplateVector<Item*, Number >* A< Number >::getList()
{
return m_list;
}
问题在于getList()
函数的.cpp定义。
它在编译时会导致错误,我不知道为什么。错误是
declaration is incompatible with "A<Number>::List *A<Number>::getList()
如果我改变:
typedef typename IA< Number >::List List
到
typedef TemplateVector<Item*, Number > List
它工作正常,但它是一个重新定义,我想避免这种警告。 (注意我需要分成.hpp和.cpp文件,我使用完整性编译器)
答案 0 :(得分:2)
我想我理解发生这种情况的理由。考虑一个演示相同问题的简单示例
template<class T>
struct base {
typedef int foo;
};
/*
struct other{};
template<>
struct base<float> {
typedef other foo;
};
*/
template<class T>
struct test {
static typename base<T>::foo bar();
};
template<class T>
int test<T>::bar() { // (1)
return 2;
}
这会产生以下错误:gcc:
a.cpp:22:5: error: prototype for ‘int test<T>::bar()’ does not match any in class ‘test<T>’
int test<T>::bar() {
^
a.cpp:18:34: error: candidate is: static typename base<T>::foo test<T>::bar()
static typename base<T>::foo bar();
^
为什么会这样?考虑编译器在遇到第(1)行时会想到什么。尽管没有模板实例化正在进行中(因此编译器无法替代T
),但它可能会尝试将函数定义的标头与其声明匹配。它看到在定义中返回类型为int
,而在声明中返回类型为typename base<T>::foo
。编译器如何知道它们与所有 T
的类型相同?
显然编译器无法推断出这一点,因为它根本就不是真的。实际上,如果您取消评论评论部分,您会发现T=float
base<T>::foo
将是other
,而不是int
。
因此,当编译器遇到第(1)行时,它永远无法确定每个 T
{em} base<T>::foo
的将是int
。 (事实上,对于某些T
,base<T>
根本没有foo
成员。)因此,如果编译器尝试在实际之前检查返回类型实例化,它没有别的办法,但失败了。
我不太擅长这个标准,所以我不能用那里的引言支持这个解释;也许我其实是错的,并且还有另一个基于标准的原因。
无论如何,正如我在评论中指出的那样,你根本不应该使用StaticInternalVersatileVector<Item*, Number >*
作为返回类型。最简单和最正确的方法是仅使用typename A<Number>::List*
。