Keep struct variables private outside, but public inside class

Hello.

My class looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
template<typename T>
struct Node
{
	T value;
	Node* left{ nullptr };
	Node* right{ nullptr };
};

template<typename T>
class GTree
{
private:
      Node<T>* root = nullptr;

public: // some public methods here...for example the Search function

	Node* Search(T const& key, Node* current)
	{
		if (!current)
			return nullptr;
		if (current->value == key)
			return current;

		if (key < current->value)
			return Search(key, current->left);

		if (key > current->value)
			return Search(key, current->right);
	}

int main()
{
	GTree<int> my{ 10 };
	my.Insert(90);
	my.Insert(4);
	my.Insert(3);
	my.Insert(7);

	my.Search(4)->left = nullptr;   // THIS SHOULDN'T BE POSSIBLE!!!
}


As you can see in the main() function, nothing forbids me from accessing the ->left member variable.

Since I don't want this to be possible, I tried another way: putting the Struct inside the class as private field and setting its members private as well

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template<typename T>
class GTree
{
private:
    struct Node
    {
private: // these fields are private!
	T value;
	Node* left{ nullptr };
	Node* right{ nullptr };
    };
    
    Node* root = nullptr;

public:
        /* BUNCH OF ERRORS HERE!!! */
	Node* Search(T const& key, Node* current)
	{
		if (!current)
			return nullptr;
		if (current->value == key)
			return current;

		if (key < current->value)
			return Search(key, current->left);

		if (key > current->value)
			return Search(key, current->right);
	}


But as expected, I get a bunch of errors inside the Search() function since in that function I'm accessing the
->value, ->left and ->right fields.

So... my last chance has been this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

template<typename T>
class GTree
{
private:
    struct Node
    {
         // HERE WE SOLVE THE PROBLEM!
         friend class GTree<T>;

    private: // these fields are private!
	  T value;
	  Node* left{ nullptr };
	  Node* right{ nullptr };
    };
    
    Node* root = nullptr;

public:
        /* NO ERRORS HERE!!! */
	Node* Search(T const& key, Node* current)
	{
		if (!current)
			return nullptr;
		if (current->value == key)
			return current;

		if (key < current->value)
			return Search(key, current->left);

		if (key > current->value)
			return Search(key, current->right);
	}
int main()
{
	GTree<int> my{ 10 };
	my.Insert(90);
	my.Insert(4);
	my.Insert(3);
	my.Insert(7);

	my.Search(4)->left = nullptr;   // ERROR!
}


As you can see, setting the GTree class as friend of the struct, now we can use all of its fields freely.
And in the meantime, we can't use those fields in the main() function.

That's what I wanted!


QUESTIONS: Is my solution recommended? Is it a good solution? Is there another way, maybe more convenient way, of accomplishing this?

Thanks!
Last edited on
Why don't you just return the value of the node ? I don't see a reason to return the whole node.
Why don't you just return the value of the node?


Because, what if in the search function the node is not found?

Like, instead of nullptr what could I return?

Imagine a BST of integers like { 4, 54, -7, 92, 1, -67, -21 }.

What do I return when my function is called like this

myTree.Search(999); // not found

With a pointer I just return nullptr... but with a value?
Last edited on
You could return a bool.

1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
  GTree<int> my{ 10 };
  my.Insert(90);
  my.Insert(4);
  my.Insert(3);
  my.Insert(7);

  if (my.Search(4)) 
  {
     // ok I know 4 is in the tree
  }
}


Topic archived. No new replies allowed.