11.1.2.  Class Templates

[ fromfile: templates.xml id: classtemplates ]

Figure 11.1.  Template-Based Stack

Template-Based Stack

Example 11.3. src/containers/stack/stack.h

[ . . . . ]

#include <QDebug>
template<class T> class Node {
 public:
    Node(T invalue): m_Value(invalue), m_Next(0) {}
    ~Node() ;
    T getValue() const {return m_Value;}
    void setValue(T value) {m_Value = value;}
    Node<T>* getNext() const {return m_Next;}
    void setNext(Node<T>* next) {m_Next = next;}
 private:
    T m_Value;
    Node<T>* m_Next;
};

template<class T> Node<T>::~Node() {
    qDebug() << m_Value << " deleted " << endl;
    if(m_Next) {
        delete m_Next; 
    }
}

template<class T> class Stack {
 public:
    Stack(): m_Head(0), m_Count(0) {}
    ~Stack<T>() {delete m_Head;} ;
    void push(const T& t);
    T pop();
    T top() const;
    int count() const;
 private:
    Node<T>* m_Head;
    int m_Count;
};


Example 11.4. src/containers/stack/stack.h

[ . . . . ]


template <class T> void Stack<T>::push(const T& value) {
    Node<T>* newNode = new Node<T>(value);
    newNode->setNext(m_Head);
    m_Head = newNode;
    ++m_Count;
}

template <class T>  T Stack<T>::pop() {
    Node<T>* popped = m_Head;
    if (m_Head != 0) {
        m_Head = m_Head->getNext();
        T retval = popped->getValue();
        popped->setNext(0);
        delete popped;
        --m_Count;
        return retval;        
    }
    return 0;
}

Example 11.5. src/containers/stack/main.cpp

#include <QDebug>
#include <QString>
#include "stack.h"

int main() {
    Stack<int> intstack1, intstack2;
    int val;
    for (val = 0; val < 4; ++val) {
        intstack1.push(val);
        intstack2.push(2 * val);
    }
    while (intstack1.count()) {
        val = intstack1.pop();
        qDebug() << val;
    }
    Stack<QString> stringstack;
    stringstack.push("First on");
    stringstack.push("second on");
    stringstack.push("first off");
    QString val2;
    while (stringstack.count()) {
        val2 = stringstack.pop();
        qDebug() << val2;
    }
    qDebug() << "Now intstack2 will self destruct.";
    return 0;
}

When you run the program, you should see the following output.

3 deleted
3
2 deleted
2
1 deleted
1
0 deleted
0
first off deleted
"first off"
second on deleted
"second on"
First on deleted
"First on"
Now intstack2 will self destruct.
6 deleted
4 deleted
2 deleted
0 deleted
[Note] Q_OBJECT and Template Classes

Because additional code needs to be generated by moc for each Q_OBJECT, and moc is not smart enough to know how to generate specializations of a template class, it is not permitted to make a class template that is also marked Q_OBJECT.



[53] This is a consequence of the fact that calling delete on a pointer automatically invokes the destructor associated with that pointer.