Question

First of all I would like to thank in advance anyone who answers this question. Your help is greatly appreciated. This is my first time posting here, so please forgive me if I post with bad etiquette.

My question is about the method prototype:

void copySubtree(Node<T> * & target, Node<T> * const & original);

and when I call copySubtree() later in combineTrees(). As the code is currently, it builds. But what I originally had was:

void copySubtree(Node<T> * & target, const Node<T> * & original);

which gave me the error:

error C2664: 'RootedBinaryTree<T>::copySubtree' : cannot convert parameter 2 from 'RootedBinaryTree<T>::Node<T> *const ' to 'const RootedBinaryTree<T>::Node<T> *&'

I know that when you put const before the data type in the parameter it prevents you from modifying said parameter in your method, but I do not know what it does when you put it after the data type, nor am I certain that my code building with the placement of const after the data type was not just a fluke. What does placing const after a data type do? Will my code have horrible runtime problems the way it is currently written?

[Also: I am in the process of trying to write the rooted binary tree template class method definitions (which is why some of the methods are empty, and there are some random notes to myself in the comments). So I apologize for any inconvenience caused by that.]

Here is the relevant code:

RootedBinaryTree.h

#ifndef ROOTEDBINARYTREE_H
#define ROOTEDBINARYTREE_H 

template <class T>
class RootedBinaryTree
{
private:
    template <class T>
struct Node
{
    T nodeData;
    Node<T> * leftChild; 
    Node<T> * rightChild; 
}; 
Node<T> * root;
Node<T> * currentPosition; 

void copySubtree(Node<T> * & target, Node<T> * const & original);
void deleteSubtree(Node<T> * n); 

public:
RootedBinaryTree(const T & rootData);
RootedBinaryTree(const RootedBinaryTree<T> & original);
~RootedBinaryTree(); 
void toRoot();
bool moveLeft();
bool moveRight(); 
T getData() const {return currentPosition->nodeData;}; 
RootedBinaryTree<T> & operator=(const RootedBinaryTree<T> & RHS);
void combineTrees(const RootedBinaryTree<T> & leftTree, const RootedBinaryTree<T> & rightTree);
void setNodeData(const T & nodeData); 
};

#endif

RootedBinaryTree.cpp

#ifndef ROOTEDBINARYTREE_CPP
#define ROOTEDBINARYTREE_CPP

#include "RootedBinaryTree.h"

template<class T>
void RootedBinaryTree<T>::copySubtree(Node<T> * & target, Node<T> * const & original) 
{
    // later add something here to delete a subtree if the node we are trying to assign to has children
    // perhaps a deleteSubtree() method

    target = new Node<T>; 
    if(original->leftChild != 0L)
    {
        copySubtree(target->leftChild, original->leftChild); 
    } 
    else
    {
        target->leftChild = 0L; 
    }
    // ^^^ copy targets left (and right) children to originals
    if(original->rightChild != 0L) 
    {
        copySubtree(target->rightChild, original->rightChild);
    }
    else
    {
        target->rightChild = 0L; 
    }
    target->nodeData = original->nodeData;

}

template <class T> 
void RootedBinaryTree<T>::deleteSubtree(Node<T> * n)                                                // Done 
{// Assumes that n is a valid node. 
    if(n->leftChild != 0L) deleteSubtree(n->leftChild);                                             // Delete all nodes in left subtree
    if(n->rightChild != 0L) deleteSubtree(n->rightChild);                                           // Delete all nodes in right subtree 
    delete n; 
}

template <class T>
RootedBinaryTree<T>::RootedBinaryTree(const T & rootData)                                           // Done
{
    root = new Node <T>; 
    root->leftChild = 0L; 
    root->rightChild = 0L; 
    root->nodeData = rootData; 
    currentPosition = root; 
}

template <class T>
RootedBinaryTree<T>::RootedBinaryTree(const RootedBinaryTree<T> & original)
{

}

template <class T>
RootedBinaryTree<T>::~RootedBinaryTree()
{
    deleteSubtree(root);                                                                            // root will be valid because of our constructor and other methods
    root = currentPosition = 0L;    
}

template <class T>
void RootedBinaryTree<T>::toRoot()                                                                  // Done
{
    currentPosition = root; 
}

template <class T>
bool RootedBinaryTree<T>::moveLeft()                                                                // Done 
{
    if(currentPosition->leftChild == 0L) return false; 
    currentPosition = currentPosition->leftChild; 
    return true; 
}

template <class T>
bool RootedBinaryTree<T>::moveRight()                                                               // Done 
{
    if(currentPosition->rightChild == 0L) return false; 
    currentPosition = currentPosition->rightChild;
    return true; 
}

template <class T>
RootedBinaryTree<T> & RootedBinaryTree<T>::operator=(const RootedBinaryTree<T> & RHS)
{

}

template <class T>
void RootedBinaryTree<T>::combineTrees(const RootedBinaryTree<T> & leftTree, const RootedBinaryTree<T> & rightTree)
{ // Copies leftTree into root's left tree and rightTree into root's right tree.
    if(root->leftChild != 0L) deleteSubtree(root->leftChild);
    if(root->rightChild != 0L) deleteSubtree(root->rightChild); 
    copySubtree(root->leftChild, leftTree.root);
    copySubtree(root->rightChild, rightTree.root);
}

template <class T>
void RootedBinaryTree<T>::setNodeData(const T & nodeData)
{
    currentPosition->nodeData = nodeData; 
}

#endif

Thanks again!

Was it helpful?

Solution

The rule is that const attaches itself to the thing on its left, and if there's nothing to the left, it attaches itself to the thing on the right. So in this case, we have:

const Node *p; // p is a pointer to a const Node
Node const *p; // same again, p is a pointer to a const Node
Node * const p; // p is a const pointer to a (mutable) Node
const Node * const p; // p is a const pointer to a const Node
Node const * const p; // same again, p is a const pointer to a const Node

Most people write const Type, because that's how we tend to think of them, but some people prefer writing Type const because of this rule.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top