是否需要使用该参数声明具有模板参数的类中的所有方法声明?编译器似乎需要类似下面的内容
// Queue.h
template <class ItemType>
class Queue
{
Queue();
ItemType dequeue();
int count();
/* ... other methods ... */
};
// Queue.cpp
template <class ItemType>
Queue<ItemType>::Queue()
{ /*...*/ }
template <class ItemType>
int Queue<ItemType>::count()
{/*...*/}
template <class ItemType>
ItemType Queue<ItemType>::dequeue()
{/* ... */}
来自Java / C#,这似乎有点多余 - 我觉得我应该能够更像这样定义方法:
int Queue::count()
签名不引用ItemType,因此我们可以省略它。
Queue::ItemType Queue::dequeue()
签名引用ItemType,但编译器知道我们正在讨论模板参数,因为我们使用Queue::
答案 0 :(得分:5)
是的,您需要提供模板参数。请注意,虽然它可能看起来多余,但事实并非如此。 C ++模板是Java泛型的一个更强大的工具,它们允许进行特化。这意味着使用基本模板Queue
可能有多个实现匹配不同的模板参数并具有不同的定义。或者,您可以使用单个Queue
模板,其中包含一些针对某些功能的特化。这两种情况要求您同时提供template
参数列表和类模板参数:
// Just member specialization
template <typename T>
struct X {
void foo() { std::cout << "generic\n"; }
};
// specialize just this member for `int`
template <>
void X<int>::foo() { std::cout << "int\n"; }
int main() {
X<double> xd; xd.foo(); // generic
X<int> xi; xi.foo(); // int
}
// Class template specialization
template <typename T>
struct X {
void foo();
}
template <typename T>
struct X<T*> {
void bar();
}
template <typename T>
void X<T>::foo() { std::cout << "generic\n"; }
template <typename T>
void X<T*>::bar() { std::cout << "ptr\n"; }
int main() {
X<int > xi; xi.foo(); // generic
X<int*> xp; xp.bar(); // ptr
}
答案 1 :(得分:2)
是的,他们这样做,并且它不是多余的,因为Queue
不是没有模板参数的类型。但是,您可以在类模板声明中提供函数定义:
template <class ItemType>
class Queue
{
Queue();
ItemType dequeue() { /* implementation */}
int count() { /* implementation */ }
/* ... other methods ... */
};
请记住这个
Queue<int> q;
int i = q.dequeue();
相当于
Queue<int> q;
int i = Queue<int>::dequeue(&q);
换句话说,需要完整类型来限定函数名称,即使函数本身没有引用模板参数(尽管在这种情况下,返回类型需要模板参数)。
答案 2 :(得分:1)
是。
当成员函数,成员类,成员枚举,静态数据成员或成员时 类模板的模板是在类模板定义之外定义的,成员定义是 定义为模板定义,其中模板参数是类模板的参数。该 成员定义中使用的模板参数的名称可能与模板不同 类模板定义中使用的参数名称。