------------------------------------------------------------------------------
MC logo
Linked List (Classes)
[^] CSc 220 Home
------------------------------------------------------------------------------
[Introduction] [Boolean and Control] [Functions] [Arrays and Pointers] [Dynamic Arrays] [Array Errors] [Command Array] [Standard Containers] [Structs and Classes] [Automatic Pointer] [Multi-File Programs] [Copying Objects] [Templates] [Inheritance] [Plain C I/O] [Type Odds And Ends] [Plain C Strings] [File I/O]
[Plain Structs] [Point With Struct] [C++ Point Class] [Linked List (Structs)] [Linked List (Classes)] [C++ v. Java Classes I] [Prime Generator Algorithm] [Fast Primes Generator]
cllnk.cpp
#include <iostream>

using namespace std;

/*
 * This program reads integers into a linked list, then prints them
 * out backwards.  This uses a more fully C++ style, making use of 
 * classes.
 */

// Linked list node structure.
class lnode
{
public:
        // Construct.
        lnode(int c, lnode *n = 0) { m_cont = c; m_next = n; }

        // Extractors.  
        lnode *next() const { return m_next; }
        int val() const { return m_cont; }
private:
        int m_cont;             // Contained node.
        lnode *m_next;  // Next node.
};

class List {
public:
        // Construct an empty list.
        List() { head = NULL; }

        // A destructor is called automatically when an object is destroyed.
        ~List() { clear(); }

        // Add an integer to the front of the list, and return the new list. 
        void add_front(int val) {
                // Insert the integer to the list head.  We don't need
                // the initialization code since the constructor does that.
                head = new lnode(val, head);
        }

        // Print the list to the stream.
        void print(ostream &strm) const {
                for(const lnode *scan = head; scan != NULL; scan = scan->next())
                        strm << scan->val() << " ";
        }

        // This frees the contents of the list.
        void clear() {
                // Go through the nodes and delete each one.
                while(head != NULL) {
                        // Remember the current list head, then advance it.
                        lnode *zombie = head;
                        head = head->next();

                        // Free the node.
                        delete zombie;
                }
        }
private:
        // The head of the list.
        lnode *head;
};

ostream & operator<<(ostream & strm, const List &list)
{
        list.print(strm);
        return strm;
}

main()
{
        // List object.
        List list;

        // Read the list contents and add each integer to the front of
        // the list.  The list is thus built in reverse order.
        int newval;
        while(cin >> newval)
                list.add_front(newval);

        cout << "-------------------------------------------------" << endl;

        // Print the list.
        cout << list << endl;

        // list.~List() is called automatically here, and it cleans
        // up the nodes.
}

So what on earth is this ~List() { clear(); } thing?

It's called a destructor. Just as a constructor is called to initialize any object when it created, a destructor is called to clean up any object when it is destroyed. In this example, its body is a one-line call to another function. That's a common pattern, but not a requirement; it's a member function and can have any appropriate function body.