[ fromfile: templates.xml id: classtemplates ]
Like functions, classes can also use parameterized types.
A class template specifies how to produce generic data structures of a particular type.
All Qt container classes and, of course, all containers in the Standard Template Library (STL) are parameterized.
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;
};
All template definitions (classes and functions) must appear in the header file.
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; }
The creation of objects is handled generically in the template function, push()
.
The destructor for the Node<T>
class recursively deletes Node
pointers until it reaches one with a zero m_Next
pointer.[53]
Controlling creation and destruction of Node<T>
objects this way enables Stack<T>
to completely manage its dynamic memory.
Example 11.5 contains some client code to demonstrate these classes.
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
Q_OBJECT and Template Classes | |
---|---|
Because additional code needs to be generated by moc for each |
[53] This is a consequence of the fact that calling delete
on a pointer automatically invokes the destructor associated with that pointer.
Generated: 2012-03-02 | © 2012 Alan Ezust and Paul Ezust. |