Accessing a private member variable without object

168 Views Asked by At
class BinarySearchTree
{
private:
    Node *root;
public:
    BinarySearchTree() ;
    ~BinarySearchTree();
    void insert_node(int, Node*);
    void print_tree(Node *);
    friend Node* get_root();

};

/**********************BinarySearchTree definition***************/
BinarySearchTree::BinarySearchTree() : root(nullptr)
{

}

Node* get_root()
{
    Node* x= root;
    return x;
}

The compiler says that error C2065: 'root' : undeclared identifier Why can't the compiler recognize root although get_root is a friend function?

Similarly, why can't I use default arguments like this?

void BinarySearchTree::insert_node(int inserted_key,Node* traverse_ptr = root);
1

There are 1 best solutions below

0
On BEST ANSWER

For your question about get_root, the compiler is smart enough to determine that get_root is a friend of BinarySearchTree. That's not the issue here. Rather, when the compiler sees this line, it doesn't know which BinarySearchTree object you're asking it to read the root from:

Node* x = root;

Think of it this way - a friend function is a free function, just like any other free function, except that it can read private fields. However, in order to read the private fields of a BinarySearchTree object, it needs to have an actual, honest-to-goodness BinarySearchTree object to read the field from.

This doesn't come up with member functions because a member function implicitly operates relative to some receiver object. In member functions of BinarySearchTree, if you talk about root, C++ interprets it to mean "the root field of the this object."

Given what you're trying to do here, I think that you should just make get_root a member function rather than a friend function. You could also change get_root so that it takes a BST as input:

Node* get_root(const BinarySearchTree& bst)
{
    return bst.root;
}

You asked a separate question about why you can't give default arguments like this:

void BinarySearchTree ::insert_node(int inserted_key, Node* traverse_ptr = root);

The C++ spec just plain doesn't allow you to use member variables as default values to member functions. I believe that this has something to do with implementation issues where the pointer you have to an object might point into the middle of an object if you're using multiple inheritance, and the offset to the field couldn't be known statically.

However, you can get around this by doing something like this:

class BinarySearchTree {
public:
    void insert_node(int inserted_key);
    void insert_node(int inserted_key, Node* traverse_ptr);
}

void BinarySearchTree::insert_node(int inserted_key) {
    insert_node(inserted_key, root);
}

void BinarySearchTree::insert_node(int inserted_key, Node* traverse_ptr) {
   ...
}

This uses overloading instead of default arguments and accomplishes more or less the same thing.