假设我有以下代码:
template<typename T>
struct Task
{
T* item;
Task* next;
int priority;
};
class PriorityQueue
{
public:
PriorityQueue();
Enqueue(T* item, int priority);
T* Dequeue();
private:
Task<T>* head;
};
上面的代码将抛出编译错误,其中 T未在PriorityQueue类中声明。如果我想引用在任务结构中定义为模板类的T *项,那么这样做的正确语法是什么?
答案 0 :(得分:1)
T
没有特殊意义。必须使用语法template<typename T>
或其变体将每个模板类或模板方法声明为模板。在这种情况下,两个T
将不会自动相同。
使用模板类时,需要使用语法classname<SomeType>
指定模板参数。正如@Antonio Garrido指出的那样;在您的情况下,这可能意味着您的主管成员应该被声明为Task<T>* head;
现在,由于Task
似乎不是接口的一部分,您也可以将它声明为PriorityQueue类的一部分。那样T
:
template<typename T>
class PriorityQueue
{
struct Task
{
T* item;
Task* next;
int priority;
}
public:
PriorityQueue();
Enqueue(T* item, int priority);
T* Dequeue();
private:
Task* head;
};
然后使用模板类:
PriorotyQueue<int> que;
auto que = PriorotyQueue<int>(); // alternatively
que.Engueue(3);
答案 1 :(得分:1)
我不确定1是如何工作的,除非你链接了一个名为T.的东西,并且在你的课程声明后你需要;
。
至于两个T是否相同,他们不是。模板的重点在于它允许您有两种类型,即#34;有点&#34;相同但有不同的类型。它们只有相同的界面。
我可以在一个程序中做这样的事情:
PriorityQueue<std::string> stringQueue;
PriorityQueue<int> intQueue;
我会有两种不同类型的队列。 stringQueue
的类型为PriorityQueue<std::string>
,intQueue
的类型为PriorityQueue<int>
。这些实际上是共享相同接口的不同类型,因为C ++编译器将为每个接口编译两个不同的二进制文件。如果我做了类似的事情:
intQueue.enqueue(5, 0);
stringQueue.enqueue("hello world", 1);
然后stringQueue
将包含Task
类型的Task<string>
,因为当PriorityQueue<std::string>::enqueue
创建新的Task
时,它会生成Task<std::string
并且与intQueue
和整数相同。
T只是一个传统的变量,但你也可以做这样的模板:
template<typename Type>
template<typename A> //these two are basically the same as T
template<Task SpecialTask> //here SpecialTask would have to be a
//Task or a child of Task
template<class C> //C must be a class
template<typename T, U, V> //here are three templates in one declaration
template<PriorityQueue PQ,
Task T,
typename U> //three of different "lineage"
那么编译器如何知道PriorityQueue<int>
应该具有Task<int>
属性?当它注意到它有一个模板属性,或者它正在新建一个模板时,就会发生这种情况,如果它没有任何已经存在的话,它会编译Task<int>
的二进制文件。
答案 2 :(得分:0)
最后一行是
Task<T>* head;
顺便说一下,你需要添加';'结束结构/类定义