C++ C++;方法定义中的模板参数

C++ C++;方法定义中的模板参数,c++,templates,C++,Templates,类中具有模板参数的所有方法声明都需要使用该参数声明吗?编译器似乎需要以下内容 // Queue.h template <class ItemType> class Queue { Queue(); ItemType dequeue(); int count(); /* ... other methods ... */ }; // Queue.cpp template <class ItemType> Queue<ItemType>

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

// 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()
{/* ... */}
签名没有引用ItemType,因此我们可以忽略它

Queue::ItemType Queue::dequeue() 

签名引用ItemType,但编译器知道我们谈论的是模板参数,因为我们用
队列::

限定标识符。是的,它们是这样做的,并且它不是多余的,因为
队列
不是没有模板参数的类型。但是,您可以在类模板声明中提供函数定义:

template <class ItemType>
class Queue
{
    Queue();
    ItemType dequeue() { /* implementation */}
    int count() { /* implementation */ }
    /* ... other methods ... */
};
模板
类队列
{
队列();
ItemType出列(){/*实现*/}
int count(){/*实现*/}
/*…其他方法*/
};
记住这一点

Queue<int> q;
int i = q.dequeue();
队列q;
int i=q.dequeue();
相当于

Queue<int> q;
int i = Queue<int>::dequeue(&q);
队列q;
int i=队列::出列(&q);

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

是的,它们需要,并且它不是多余的,因为
队列
不是没有模板参数的类型。但是,您可以在类模板声明中提供函数定义:

template <class ItemType>
class Queue
{
    Queue();
    ItemType dequeue() { /* implementation */}
    int count() { /* implementation */ }
    /* ... other methods ... */
};
模板
类队列
{
队列();
ItemType出列(){/*实现*/}
int count(){/*实现*/}
/*…其他方法*/
};
记住这一点

Queue<int> q;
int i = q.dequeue();
队列q;
int i=q.dequeue();
相当于

Queue<int> q;
int i = Queue<int>::dequeue(&q);
队列q;
int i=队列::出列(&q);
换句话说,即使函数本身没有引用模板参数,也需要完整类型来限定函数名(尽管在这种情况下,返回类型需要模板参数)。

是。

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

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


是的,您需要提供模板参数。请注意,虽然它看起来可能是多余的,但实际上并非如此。C++模板是java泛型的一个更强大的工具,它们允许专门化。这意味着,对于一个基本模板
Queue
,可能有多个实现匹配不同的模板参数并具有不同的定义。或者,对于某些函数,您可以使用一个带有多个专门化的
队列
模板。这两种情况要求您同时提供
模板
参数列表和类模板参数:

// 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
}
//只是成员专门化
样板
结构X{

void foo(){STD::CUT< P>是的,您需要提供模板参数。注意,虽然它看起来可能是冗余的,但不是。C++模板是java泛型的更强大的工具,并且允许专门化。这意味着,使用基础模板<代码>队列< /> >可能有多个实现不同模板参数的实现。s和具有不同的定义。或者,您可以为某些函数使用具有多个专门化的单个
队列
模板。这两种情况要求您同时提供
模板
参数列表和类模板参数:

// 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
}
//只是成员专门化
样板
结构X{

void foo(){std::cout如果不是专门化,就不需要这样做(示例为Java):语言中的语法可以使用模板的名称引用实例化后获得的类型,就像在类模板的定义中一样。如果不是专门化,就不需要这样做(示例为Java):语言中的语法可以使用模板的名称来引用实例化后获得的类型,就像在类模板的定义中一样。从技术上讲,您不是在询问声明,而是在类模板中声明的成员的定义。从技术上讲,您不是在问关于声明,但关于类模板中声明的成员的定义。