I got the following code out of Carrano's Walls & Mirrors. I made a few changes but have tested it and it works. I'm really confused by line 19 in the .h file. Why is it structured like "void (*FunctionType)"?

Why not (void*) FunctionType?
or void* FunctionType?

What is the significance of the parenthesis being around the *FunctionType? I've tried changing this and it only works if I leave it the way it is.

Thanks
Jake

/********************************************************************************************************************************
* @file:		BinaryTree.h
* @purpose:	Specification for the binary tree to be used for representing math equations (from Carrano's implementation
*						in Walls & Mirrors Fifth Edition)
* @author:	Frank M. Carrano 
* @date:		10/1/09
*******************************************************************************************************************************/
#ifndef BINARYTREE_H
#define BINARYTREE_H

#include "KeyedItem.h"
#include "TreeException.h"
#include "TreeNode.h"
#include <cstddef> // definition of NULL
#include <new>
#include <iostream>
using namespace std;

typedef void (*FunctionType)(TreeNode* curNode); // the function to be called during inorder traversal

/*******************************************************************************************************************************
* @class:		BinaryTree
* @purpose:	Implementation of a binary tree to be used in expressing math equations
*******************************************************************************************************************************/
class BinaryTree {
 public:
	BinaryTree();

	BinaryTree(const TreeItemType& rootItem) throw(TreeException);

	BinaryTree(const TreeItemType& rootItem, BinaryTree& leftTree, BinaryTree& rightTree) throw(TreeException);

	BinaryTree(BinaryTree& tree) throw(TreeException);

	virtual ~BinaryTree();

	virtual bool isEmpty() const;

	virtual TreeItemType getRootData() const throw(TreeException);

	virtual void setRootData(const TreeItemType& newItem) throw(TreeException);

	virtual TreeNode* attachLeft(const TreeItemType& newItem) throw(TreeException);

	virtual TreeNode* attachRight(const TreeItemType& newItem) throw(TreeException);

	virtual void attachLeftSubtree(BinaryTree& leftTree) throw(TreeException);

	virtual void attachRightSubtree(BinaryTree& rightTree) throw(TreeException);

	virtual void detachLeftSubtree(BinaryTree& leftTree) throw(TreeException);

	virtual void detachRightSubtree(BinaryTree& rightTree) throw(TreeException);

	virtual BinaryTree getLeftSubtree() const throw(TreeException);

	virtual BinaryTree getRightSubtree() const throw(TreeException);

	virtual BinaryTree& operator=(const BinaryTree& rhs) throw(TreeException);

	/********************************************************************************************************************************
	* @purpose: public method that calls the protected method inOrder, to display every node in the tree in in-order representation
	*	@param:		pointer to the function that will visit each node
	*******************************************************************************************************************************/
	virtual void inOrderTraverse(FunctionType visit); 

	virtual void preOrderTraverse(FunctionType visit);

	TreeNode *rootPtr() const;

 protected:
	BinaryTree(TreeNode *nodePtr);

	void copyTree(TreeNode *treePtr, TreeNode *& newTreePtr) const throw(TreeException);

	/********************************************************************************************************************************
	* @purpose:	Deallocates memory used by tree and deletes the tree  
	* @param:		Pointer to the tree in question
	*******************************************************************************************************************************/
	void destroyTree(TreeNode* treePtr) throw(TreeException);

	void inOrder(TreeNode *nodePtr, FunctionType visit); // this is protected because it has access to every node in the tree

	void preOrder(TreeNode *nodePtr, FunctionType visit);

	void setRootPtr(TreeNode *newRoot);

	void getChildPtrs(TreeNode *nodePtr, TreeNode *& leftChildPtr, TreeNode *& rightChildPtr) const;

	void setChildPtrs(TreeNode *nodePtr, TreeNode *leftChildPtr, TreeNode *rightChildPtr);

	TreeNode *root; // Pointer to the root of the tree
	
};

#endif

/********************************************************************************************************************************
* @file: 		BinaryTree.cpp
* @purpose:	Implementation for the binary tree to be used for representing math equations (from Carrano's implementation
*						in Walls & Mirrors Fifth Edition)
* @author:	Frank M. Carrano
* @date: 		10/2/09
*******************************************************************************************************************************/

#include "BinaryTree.h"

BinaryTree::BinaryTree() : root(NULL){
}

BinaryTree::BinaryTree(const TreeItemType& rootItem) throw(TreeException)
{
	try{
		root = new TreeNode(rootItem, NULL, NULL);
	}
	catch(bad_alloc e){
		delete root;
		throw TreeException("TreeException: constructor cannot allocate memory");
	}
}

BinaryTree::BinaryTree(const TreeItemType& rootItem, BinaryTree& leftTree, BinaryTree& rightTree) throw(TreeException){
	try{
		root = new TreeNode(rootItem, NULL, NULL);
		attachLeftSubtree(leftTree);
		attachRightSubtree(rightTree);
	}
	catch(bad_alloc e){
		delete root;
		throw TreeException("TreeException: constructor cannot allocate memory");
	}
}

BinaryTree::BinaryTree(BinaryTree& tree) throw(TreeException){
	try{
		copyTree(tree.root, root);
	}
	catch(bad_alloc e){
		destroyTree(tree.root);
		throw TreeException("TreeException: copy constructor cannot allocate memory");
	}
}

BinaryTree::BinaryTree(TreeNode *nodePtr) : root(nodePtr){
}

BinaryTree::~BinaryTree(){
	destroyTree(root);
	root = NULL;
}

bool BinaryTree::isEmpty() const{
	return(root == NULL);
}

TreeItemType BinaryTree::getRootData() const throw(TreeException){
	if(isEmpty())
		throw TreeException("TreeException: Empty tree");
	return root->item;
}

void BinaryTree::setRootData(const TreeItemType& newItem) throw(TreeException){
	if(!isEmpty()){
		root->item = newItem;
	}
	else{
		try{
			root = new TreeNode(newItem, NULL, NULL);
		}
		catch(bad_alloc e){
			throw TreeException("TreeException: setRootData cannot allocate memory");
		}
	}
}

TreeNode* BinaryTree::attachLeft(const TreeItemType& newItem) throw(TreeException){
	if(isEmpty())
		throw TreeException("TreeException: Empty tree");
	else if(root->leftChildPtr != NULL)
		throw TreeException("TreeException: Cannot overwrite left subtree");
	else{
		try{
			root->leftChildPtr = new TreeNode(newItem, NULL, NULL);
			return root->leftChildPtr;
		}
		catch(bad_alloc e){
			throw TreeException("TreeException: attachLeft cannot allocate memory");
		}
	}
}

TreeNode* BinaryTree::attachRight(const TreeItemType& newItem) throw(TreeException){
	if(isEmpty())
		throw TreeException("TreeException: Empty tree");
	else if(root->rightChildPtr != NULL)
		throw TreeException("TreeException: Cannot overwrite right subtree");
	else{
		try{
			root->rightChildPtr = new TreeNode(newItem, NULL, NULL);
			return root->rightChildPtr;
		}
		catch(bad_alloc e){
			throw TreeException("TreeException: attachRight cannot allocate memory");
		}
	}
}

void BinaryTree::attachLeftSubtree(BinaryTree& leftTree) throw(TreeException){
	if(isEmpty())
		throw TreeException("TreeException: Empty tree");
	else if(root->leftChildPtr != NULL)
		throw TreeException("TreeException: Cannot overwrite left subtree");
	else{
		root->leftChildPtr = leftTree.root;
		leftTree.root = NULL;
	}
}

void BinaryTree::attachRightSubtree(BinaryTree& rightTree) throw(TreeException){
	if(isEmpty())
		throw TreeException("TreeException: Empty tree");
	else if(root->rightChildPtr != NULL)
		throw TreeException("TreeException: Cannot overwrite right subtree");
	else{
		root->rightChildPtr = rightTree.root;
		rightTree.root = NULL;
	}
}

void BinaryTree::detachLeftSubtree(BinaryTree& leftTree) throw(TreeException){
	if(isEmpty())
		throw TreeException("TreeException: Empty tree");
	else{
		leftTree = BinaryTree(root->leftChildPtr);
		root->leftChildPtr = NULL;
	}
}

void BinaryTree::detachRightSubtree(BinaryTree& rightTree) throw(TreeException){
	if(isEmpty())
		throw TreeException("TreeException: Empty tree");
	else{
		rightTree = BinaryTree(root->rightChildPtr);
		root->rightChildPtr = NULL;
	}
}

BinaryTree BinaryTree::getLeftSubtree() const throw(TreeException){
	TreeNode *subTreePtr;
	if(isEmpty()){
		BinaryTree emptyTree;
		return emptyTree;
	}
	else{
		copyTree(root->leftChildPtr, subTreePtr);
		BinaryTree leftTree(subTreePtr);
		return leftTree;
	}
}

BinaryTree BinaryTree::getRightSubtree() const throw(TreeException){
	TreeNode *subTreePtr;
	if(isEmpty()){
		BinaryTree emptyTree;
		return emptyTree;
	}
	else{
		copyTree(root->rightChildPtr, subTreePtr);
		BinaryTree rightTree(subTreePtr);
		return rightTree;
	}
}

BinaryTree& BinaryTree::operator=(const BinaryTree& rhs) throw(TreeException){
	if(this != &rhs){
		destroyTree(root);
		copyTree(rhs.root, root);
	}
	return *this;
}

void BinaryTree::copyTree(TreeNode *treePtr, TreeNode *& newTreePtr) const throw(TreeException){
	if(treePtr != NULL){
		try{
			newTreePtr = new TreeNode(treePtr->item, NULL, NULL);
			copyTree(treePtr->leftChildPtr, newTreePtr->leftChildPtr);
			copyTree(treePtr->rightChildPtr, newTreePtr->rightChildPtr);
		}
		catch(bad_alloc e){
			throw TreeException("TreeException: copyTree cannot allocate memory");
		}
	}
	else
		newTreePtr = NULL;
}
	
void BinaryTree::destroyTree(TreeNode* treePtr) throw(TreeException){
	if(treePtr != NULL){
		destroyTree(treePtr->leftChildPtr);
		destroyTree(treePtr->rightChildPtr);
		delete treePtr;
		treePtr = NULL;
		if(treePtr == root) { // get rid of the root
			delete root;
			root = NULL;
		}
	}
}

TreeNode *BinaryTree::rootPtr() const {
	return root;
}

void BinaryTree::setRootPtr(TreeNode *newRoot){
	root = newRoot;
}

void BinaryTree::getChildPtrs(TreeNode *nodePtr, TreeNode *& leftPtr, TreeNode *& rightPtr) const {
	leftPtr = nodePtr->leftChildPtr;
	rightPtr = nodePtr->rightChildPtr;
}

void BinaryTree::setChildPtrs(TreeNode *nodePtr, TreeNode * leftPtr, TreeNode * rightPtr) {
	nodePtr->leftChildPtr = leftPtr;
	nodePtr->rightChildPtr = rightPtr;
}

void BinaryTree::inOrderTraverse(FunctionType visit){
	inOrder(root, visit);
}

void BinaryTree::inOrder(TreeNode* nodePtr, FunctionType visit) {
	if(nodePtr != NULL){
		inOrder(nodePtr->leftChildPtr, visit);
		visit(nodePtr);
		inOrder(nodePtr->rightChildPtr, visit);
	}
}

void BinaryTree::preOrderTraverse(FunctionType visit) {
	preOrder(root, visit);
}

void BinaryTree::preOrder(TreeNode* nodePtr, FunctionType visit) {
	if(nodePtr != NULL) {
		visit(nodePtr);
		preOrder(nodePtr->leftChildPtr, visit);
		preOrder(nodePtr->rightChildPtr, visit);
	}
}

>>Why not (void*) FunctionType?
or void* FunctionType?

Otherwise it won't be a function pointer

The above statement, (void*) FunctionType , or void* FunctionType?
are the same.

void (*pF) ();
means that pf is a void pointer function. If the parenthesis wasn't there
then it would be a regular function that returns a void pointer.

Thanks, that makes sense. My next question is how do I implement this function? I want to implement it within a different class and for the function to have access to members within its class. Is this possible?

Jake

The pointer point to the variable instead of copyinfg it. Any chages made to the variable by  the function will change the variable in main also
This article has been dead for over six months. Start a new discussion instead.