如果我们有一个标准班级:
class Foo {
public:
int fooVar = 10;
int getFooVar();
}
getFooVar()
的实现为:
int Foo::getFooVar() {
return fooVar;
}
但是在模板化类中:
template <class T>
class Bar {
public:
int barVar = 10;
int getBarVar();
}
getBarVar()
的实现必须是:
template <class T>
int Bar<T>::getBarVar(){
return barVar();
}
考虑到函数未使用的事实,为什么在template <class T>
和getBarVar
的函数实现之前必须有Bar<T>::
行(与Bar ::相对)任何模板变量?
答案 0 :(得分:6)
您需要它,因为Bar
不是一个类,它是一个模板。 Bar<T>
是课程。
答案 1 :(得分:3)
Bar
本身是模板。
但是现在让我们假设您不需要它,毕竟,您指定了它,然后我添加了另一个模板参数:
template<typename T1, typename T2>
class Bar
{
void something();
};
为什么:
template<typename T1, typename T2>
void Bar<T1, T2>::something(){}
不是:
void Bar::something(){}
如果您想专门针对一种类型T1而不是另一种类型的实现,将会发生什么?您将需要添加该信息。这就是该template
声明起作用的地方,以及为什么您还需要在常规实现(IMHO)中使用它。
template<typename T>
void Bar<T, int>::something(){}
答案 2 :(得分:1)
实例化该类时,编译器将检查实现是否存在。但是在编写代码时,最终类型(即实例化类型)尚不清楚。
因此,编译器会为您实例化定义,如果编译器应实例化某些内容,则需要对其进行模板化。
答案 3 :(得分:0)
对此问题的任何回答都归结为“因为该标准如此规定”。但是,让我们检查一下禁止(因为这些错误有助于我们理解该语言的期望),而不是背诵标准语言。 “单个模板”情况很快就用完了,因此,请考虑以下内容:
template<class T>
class A
{
template<class X>
void foo(X);
};
也许我们可以对两者都使用一个模板参数?
template<class U>
void A<U>::foo(U u)
{
return;
}
error: out-of-line definition of 'foo' does not match any declaration in 'A<T>'
不,我们不能。好吧,也许是这样?
template<class U>
void A<U>::foo<U>(U u)
{
return;
}
error: cannot specialize a member of an unspecialized template
不。这吗?
template<class U, class V>
void A<U>::foo(V u)
{
return;
}
error: too many template parameters in template redeclaration
如何使用默认值模拟匹配?
template<class U>
template<class V = U>
void A<U>::foo(V u)
{
return;
}
error: cannot add a default template argument to the definition of a member of a class template
很明显,编译器担心匹配声明。这是因为编译器不将模板定义与特定的调用(就像从一种功能语言使用的那样)进行匹配,而是将其与模板声明进行匹配。 (到目前为止的代码here)。
因此,在基本级别上,答案是“因为模板定义必须与模板声明匹配”。这仍然留下了一个问题:“为什么我们不能只省略类模板参数呢?” (据我所知模板没有模棱两可的地方,所以重复模板参数无济于事)
答案 4 :(得分:0)
考虑功能模板声明
tempalte <typename T>
void foo();
现在是一个定义
void foo() { std::cout << "Hello World"; }
是以上模板的特化或过载。您必须选择两者之一。例如
#include <iostream>
template <typename T>
void foo();
void foo() { std::cout << "overload\n"; }
template <typename T>
void foo() { std::cout << "specialization\n"; }
int main() {
foo();
foo<int>();
}
打印:
overload
specialization
您的问题的简短答案是:规则是这样的,尽管如果您可以从模板的定义中省略template <typename T>
,则将需要另一种方式来定义重载。