I've been working on an assignment and now I'm stuck with buggy destructors. I have to create a generic binary tree with all the usual member functions and some special operators. There's also a restriction: everything must work iteratively so no nasty recursive hacks this time.
There is obviously something very wrong with the destructor of BinTreeNode class because if I delete the node like this:
BinTreeNode<int> * node = new BinTreeNode<int>();
delete node; 
I can still access its data:
node->getData(); //should fail miserably
so deletion has no effect but I have no usable idea how I should correct the destructor. It seems to me that the algorithm should be about right so I suspect there's something wrong with how I use pointers but at this point I'm so confused that I don't even understand my own code.
Code I have this far:
BinTree.h
#ifndef BINTREE_H_
#define BINTREE_H_
#ifndef NULL
#define NULL 0
#endif
#include "BinTreeNode.h"
template <class T>
class BinTree
{
    private:
        BinTreeNode<T> * root;
    public:
        //constructors and destructor
        BinTree():
            root(NULL){}
        BinTree(T data):
            root(new BinTreeNode<T>(data)){}
        ~BinTree();
        //search
        BinTreeNode<T> * search(T data);
        //insert
        bool insert(T data);
        //remove
        bool remove(T data);
};
template <class T>
BinTree<T>::~BinTree()
{
    delete root;
}
template <class T>
BinTreeNode<T> * BinTree<T>::search(T data)
{
    BinTreeNode<T> * node = new BinTreeNode<T>(data);
    BinTreeNode<T> * current = root;
    while (current != NULL)
    {
        if (*current == *node)
        {
            delete node;
            return root;
        }
        else if (*node < *current)
        {
            current = current->getLeft();
        }
        else
        {
            current = current->getRight();
        }
    }
    delete node;
    return NULL;
}
template <class T>
bool BinTree<T>::insert(T data)
{
    BinTreeNode<T> * node = new BinTreeNode<T>(data);
    BinTreeNode<T> * current = root;
    while (current != NULL)
    {
        if (*current == *node)
        {
            delete node;
            return false;
        }
        else if (*node < *current)
        {
            if (current->getLeft() == NULL)
            {
                current->setLeft(node);
                return true;
            }
            else
            {
                current = current->getLeft();
            }
        }
        else
        {
            if (current->getRight() == NULL)
            {
                current->setRight(node);
                return true;
            }
            else
            {
                current = current->getRight();
            }
        }
    }
    return false;
}
#endif
BinTreeNode.h
#ifndef BINTREENODE_H_
#define BINTREENODE_H_
#ifndef NULL
#define NULL 0
#endif
template <class T>
class BinTreeNode
{
    private:
        T data;
        BinTreeNode<T> *left, *right, *parent;
    public:
        //constructors and destructor
        BinTreeNode():
            data(NULL), left(NULL), right(NULL), parent(NULL){}
        BinTreeNode(T data):
            data(data), left(NULL), right(NULL), parent(NULL){}
        ~BinTreeNode();
        //set and get data member
        T getData() const;
        void setData(T data);
        //set and get left and right branches
        BinTreeNode<T> * getLeft() const;
        BinTreeNode<T> * getRight() const;
        void setLeft(BinTreeNode<T> * node);
        void setRight(BinTreeNode<T> * node);
        //set and get parent
        BinTreeNode<T> * getParent() const;
        void setParent(BinTreeNode<T> * node);
        //comparison operators
        bool operator<(const BinTreeNode<T>& node) const;
        bool operator>(const BinTreeNode<T>& node) const;
        bool operator==(const BinTreeNode<T>& node) const;
};
template <class T>
BinTreeNode<T>::~BinTreeNode()
{
    BinTreeNode<T> * current = this;
    BinTreeNode<T> * parent = NULL;
    while (current != NULL)
    {
        parent = current->getParent();
        if (current->getLeft() == NULL)
            current = current->getLeft();
        else if (current->getRight() == NULL)
            current = current->getRight();
        else
        {
            if (parent->getRight() == current)
                parent->setRight(NULL);
            else
                parent->setLeft(NULL);
             current = NULL; // this line (among others) is very suspicious
        }
        current = parent;
    }
}
template <class T>
T BinTreeNode<T>::getData() const
{
    return data;
}
template <class T>
void BinTreeNode<T>::setData(T data)
{
    this->data = data;
}
template <class T>
BinTreeNode<T> * BinTreeNode<T>::getLeft() const
{
    return left;
}
template <class T>
BinTreeNode<T> * BinTreeNode<T>::getRight() const
{
    return right;
}
template <class T>
void BinTreeNode<T>::setLeft(BinTreeNode<T> * node)
{
    node->setParent(this);
    left = node;
}
template <class T>
void BinTreeNode<T>::setRight(BinTreeNode<T> * node)
{
    node->setParent(this);
    right = node;
}
template <class T>
BinTreeNode<T> * BinTreeNode<T>::getParent() const
{
    return parent;
}
template <class T>
void BinTreeNode<T>::setParent(BinTreeNode<T> * node)
{
    parent = node;
}
template <class T>
bool BinTreeNode<T>::operator<(const BinTreeNode<T>& node) const
{
        return this->data < node.data;
}
template <class T>
bool BinTreeNode<T>::operator>(const BinTreeNode<T>& node) const
{
    return this->data > node.data;
}
template <class T>
bool BinTreeNode<T>::operator==(const BinTreeNode<T>& node) const
{
    return this->data == node.data;
}
#endif /* BINTREENODE_H_ */