Stack.h的接口
#include "stdafx.h"
//use linkedlist to implement the stack
//which is different from using the array to implement the stack
#ifndef STACK_H
#define STACK_H
using namespace std;
namespace stackNameSpace {
template<class T>
struct StackNode {
T value;
T min_value; //current local min value
StackNode* next;
};
typedef StackNode<class T>* StackNodePtr;
template<class T>
class Stack {
private:
StackNodePtr top;
public:
Stack();
Stack(const Stack& a_stack);
~Stack();
bool empty() const;
T pop();
void push(T the_value);
T getMin();
};
} //end of namespace
#endif
stack.h的实现
#include "stdafx.h"
//use linkedlist to implement the stack
//which is different from using the array to implement the stack
#ifndef STACK_CPP
#define STACK_CPP
#include <iostream>
#include <cstdlib>
#include "Stack.h"
using namespace std;
namespace stackNameSpace {
template<class T>
Stack<T>::Stack() : top(NULL) //here should be Stack<T> instead of Stack
{}
template<class T>
Stack<T>::Stack(const Stack& a_stack) {
if (a_stack.top == NULL) {
return NULL;
}
else {
StackNodePtr currentOld = a_stack.top;
//construct the top of the new stack
StackNodePtr currentNew = new StackNode<class T>;//the struct
currentNew->value = currentOld->value;
currentNew->min_value = currentOld->min_value;
top = currentNew;
//contruct the rest node in the stack
currentOld = currentOld->next;
while (currentOld != NULL) {
currentNew->next = new StackNode<class T>;
currentNew = currentNew->next;
currentNew->value = currentOld->value;
currentNew->min_value = currentOld->min_value;
currentOld = currentOld->next;
}
currentOld->next = NULL;
}
}
template<class T>
Stack<T>::~Stack() {
T data;
while (!empty()) {
data = pop();
}
}
template<class T>
bool Stack<T>::empty() const {
return (top == NULL);
}
template<class T>
T Stack<T>::pop() {
if (empty()) {
cout << "Error: popping an empty stack.\n";
exit(1);
}
T result = top->value;
StackNodePtr temp = new StackNode<class T>;
temp = top;
top = top->next;
delete temp;
return result;
}
template<class T>
void push(T the_value) {
StackNodePtr temp = new StackNode<class T>;
temp->value = the_value;
temp->min_value = min(the_value, getMin());//This is Much better
//temp->min_value = top->min_value; //This is NOT secure, since top may be NULL
temp->next = top; //update the top node
top = temp;
}
template<class T>
T getMin() {
if (top == NULL)
return INT_MAX;
else {
return top->min_value;
}
}
} //end of namespace
#endif
使用Stack类的函数
#include "stdafx.h"
#include <iostream>
#include "Stack.h" //this is not the <stack>, which is STL
//using namespace std; //NOTE: this must be wrong! because can not use multiple namespace at the same time
using namespace stackNameSpace;
using std::cout;
using std::endl;
int main() {
Stack<int> sWithMin;
sWithMin.push(5);
cout<< sWithMin.getMin() << endl;
sWithMin.push(4);
cout<< sWithMin.getMin() << endl;
sWithMin.push(5);
cout<< sWithMin.getMin() << endl;
sWithMin.push(3);
cout<< sWithMin.getMin() << endl;
sWithMin.push(6);
cout<< sWithMin.getMin() << endl;
return 0;
}
当我编译项目时,我在main()中得到一个错误“错误C2079:'stackNameSpace :: StackNode :: value'使用未定义的类'stackNameSpace :: T'”
我无法弄清楚它有错误的原因。有人可以帮帮我吗?
答案 0 :(得分:2)
namespace stackNameSpace { template<class T> struct StackNode { T value; T min_value; //current local min value StackNode* next; };
因此StackNode
是一个依赖于类型参数T
的模板。
typedef StackNode<class T>* StackNodePtr;
这不是模板定义的一部分,class T
指的是名为T.的类
(实际上class T
总是引用一个名为T的类,但构造template <class T>
除外,它可以被template <typename T>
替换。带有类型参数{{1}的模板定义必须使用普通T
,而不是T
来引用该类型。)
由于您还没有声明一个名为class T
的类,T
定义会在周围的命名空间范围内隐式声明一个不完整的类类型(即不完整的类类型为StackNodePtr
)。
::stackNameSpace::T
现在,此处template<class T>
class Stack {
private:
StackNodePtr top;
不依赖于模板参数StackNodePtr
。相反,它是指向固定类型T
的指针,而StackNode<::stackNameSpace::T>
将是与top->value
的模板参数无关的不完整类型class T
。
如果你使用Stack
并在这样的堆栈中使用Stack<int>
实例化任何内容,你会看到你显示的错误。
top->value
文件中。相反,它们应该位于使用模板的头文件中。
答案 1 :(得分:1)
虽然JoergB正确地指出了您发布的代码的问题,但我想对他在答案的最后部分解释的内容有所了解。
在Visual Studio中使用模板时,我会确保该类的标头和实现属于单个编译单元。尝试将Stack.cpp重命名为Stack.inl并将其包含在Stack.h的末尾
void push(T the_value);
T getMin();
};
} //end of namespace
#include "Stack.inl"
#endif
请务必从构建中排除Stack.inl。在解决方案资源管理器中右键单击它&gt;属性&gt;从构建中排除&gt;是。