0

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'”

我无法弄清楚它出现错误的原因。有人可以帮我吗?

4

2 回答 2

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>。对于带有类型参数的模板定义,T该类型必须使用 plain 引用T,而不是class T。)

由于您尚未声明一个已命名的类T,因此该StackNodePtr定义在周围的命名空间范围内隐式声明了一个不完整的类类型(即,不完整的类类型是::stackNameSpace::T)。

template<class T>
class Stack {
private:
      StackNodePtr top;

现在这里StackNodePtr不依赖于模板参数T。相反,它是一个指向固定类型的指针,StackNode<::stackNameSpace::T>并且是与模板参数无关top->value的不完整类型。class TStack

如果您在这样的堆栈中使用Stack<int>并实例化任何使用top->value,您将看到您显示的错误。

顺便说一句:另一个不相关的问题是模板的定义(包括类模板的成员函数)必须在模板实例化的地方可见。通常这意味着您不应将模板成员定义放入cpp单独编译的文件中。相反,它们应该位于使用模板的任何地方都包含的头文件中。

于 2013-04-19T22:13:41.153 回答
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。在解决方案资源管理器中右键单击它 > 属性 > 从构建中排除 > 是。

于 2013-04-19T22:17:19.790 回答