EDIT: This answer was based on the assumption that the OP was concluding "there is no deletion" because he was expecting to see a NULL pointer in the calling location. If that is not the case he will need to clarify what is leading to that conclusion. As is there is no reason to think the OP's code is not deleting whatever p points to.
p is passed by value into the deleteandnull function. Therefore only a local copy of the pointer is set to NULL. Assuming you have code like this somewhere:
ProductNode *ptr = // Somehow initialize to the parent of the node to delete
.
.
deleteandnull(ptr->left);
You need to add this after the call to deletandnull
ptr->left = NULL;
Note that it is not necessary to test for NULL before calling delete. It will do so itself. And since p in deleteandnull is a local, there is no point to setting it to NULL. So the whole code might as well be reduced to:
ProductNode *ptr = // Somehow initialize to the parent of the node to delete
.
.
delete ptr->left;
ptr->left = NULL;
All that said, in modern C++ you should not be using bare pointers, new and delete. Prefer to use smart pointers, for instance as in the Boost library.