1

具有模板参数的类中的所有方法声明都需要使用该参数声明吗?编译器似乎想要类似下面的东西

// 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::

4

3 回答 3

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
}
于 2012-09-09T14:33:04.677 回答
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);

换句话说,需要完整类型来限定函数名,即使函数本身没有引用模板参数(尽管在这种情况下,返回类型需要模板参数)。

于 2012-09-09T14:19:21.873 回答
1

是的。

当在类模板定义之外定义成员函数、成员类、成员枚举、静态数据成员或类模板的成员模板时,成员定义被定义为模板定义,其中模板参数是类模板的那些。成员定义中使用的模板参数名称可能与类模板定义中使用的模板参数名称不同。

于 2012-09-09T14:20:09.243 回答