How do I refer to an object inside it's own class in c++? [closed]
I am writing an implementation of binary tree in C++. I have written the implementation in Python but I am not able to understand how to refer to an object inside the class in C++. for example, in Python the code to insert a node would be:
def insert( self, val):
if self.data == val:
pass
elif val < self.data:
if self.left:
self.left.insert(val)
else:
self.left = Node(val)
else:
if self.right:
self.right.insert(val)
else:
self.right = Node(val)
but in C++, there is no self object to refer to:
class Node{
public:
int data;
Node * leftChild;
Node * rightChild;
void insert(int x){
if ( x == nullptr){
do stuff
}
}
};
What should I insert in place of X to refer to the object of the class itself inside it like the "self" keyword in python ?
Solution 1:
In a member function (like your Node::insert()
), all members of the class, e.g. data
, are accessible simply by their unqualified names.
The name is accessible without prefix because a (non-static) member function can only be called from an object of the class, e.g. Node n; n.insert(1);
. n
is the object, and the compiler will interpret data
as the data
belonging to n
.
I don't know Python but I assume that the self
parameter corresponds to C++'s implicit this
parameter which is available in every non-static member function and points to the object the function is called with, here n
. The difference is apparently that this
is implicitly passed; it does not appear explicitly in the parameter list. That is a somewhat arbitrary early C++ design decision; Bjarne Stroustrup could as well have made the parameter explicit. The main benefit is a reduction in redundancy (this
is always there for a non-static member function, so why mention it?).
Therefore, if you like you can prefix data
with this->
to be explicit. That may have some merit for long functions in classes with many members where the casual reader is unsure whether data
is a member of local variable or parameter. Some anal coding guidelines require this->
for those reasons, but typically it's only done to resolve ambiguities like name clashes with global variables. A better way to avoid name clashes and recognize members is to require an m...
prefix for them, as in mData
or m_data
, depending on your naming habits.
The code to insert a new value in the tree and not do anything if it's already there looks very much like your Python blueprint:
void insert(int val){
if (data == val)
return;
else if (val < data)
if (left)
left.insert(val);
else
left = Node(val);
else
if (right)
right.insert(val);
else
right = Node(val);
}
This is untested and probably contains typos and perhaps an if/else logic error. In real code I would always curly-brace all code that depends on an if/else, even if it's just one line. That makes maintenance easier: Removing or adding branches here may inadvertently change the association of else blocks or introduce a syntax error.
By the way, the comparison of an integer with a pointer in your original suggestion is weird and does not serve a purpose; generally such comparisons are unusual, and the pointer should be cast to a suitable integer type for that (probably std::intptr_t
).