模板继承类中的函数定义错误

时间:2015-09-17 10:29:39

标签: c++ templates typedef

我遇到了模板类和继承问题,我无法弄清楚。 这是使用过的课程。

带有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文件,我使用完整性编译器)

1 个答案:

答案 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。 (事实上​​,对于某些Tbase<T>根本没有foo成员。)因此,如果编译器尝试在实际之前检查返回类型实例化,它没有别的办法,但失败了。

我不太擅长这个标准,所以我不能用那里的引言支持这个解释;也许我其实是错的,并且还有另一个基于标准的原因。

无论如何,正如我在评论中指出的那样,你根本不应该使用StaticInternalVersatileVector<Item*, Number >*作为返回类型。最简单和最正确的方法是仅使用typename A<Number>::List*