I am currently learning C++ from Stroustrup's Programming: Principles and Practice and there is an example I cannot really understand. There is a class called Link which looks like this.
class Link{
public:
Link(Link* p=nullptr, Link* n=nullptr, const std::string& label);
Link* erase();
private:
std::string label;
Link* succ;
Link* prev;
};
Link* Link::erase() {
if (this == nullptr) return nullptr;
if(prev) prev->succ = succ;
if(succ) succ->prev = prev;
return succ;
}
What I do not understand is why
prev->succ = succ;
is correct since I am assigning to a private member of an object from an other object. What am I missing here?
Access is per class not per object. Many things would not work as they do if access would be per instance. For example this type
class foo {
int x;
};
Has a compiler generated copy constructor which is something like this:
foo::foo(const foo& other) {
x = other.x;
}
Access restictions are for encapsulation and encapsulation is to make sure that the class invariants are not violated. However, typically invarants are violated temporarily inside methods. For example consider this class
class Sum {
int a = 0;
int b = 0;
int sum = 0;
public:
void set(int x,int y);
int get_sum() { return sum; }
};
The invariant here is that sum
is always the sum of a
and b
. However, inside the set
method...
void Sum::set(int x,int y) {
a = x;
b = y;
sum = a + b;
}
This invariant is only restored on the very last line. It is your responsibility to restore the invariant such that from outside view it always holds.
Further, access restriction is to hide implementation details. In the Sum
example, the user has no knowledge that the member sum
exists and they need not know about it. However, the definition of the class methods are dealnig with implementation details. Dealing with implementation details of a different object makes no difference, because they are the same.
What is the relation to your example?
The purpose of access restrictions is to allow you to make sure from outside invariants are never violated and to hide implementation details. Inside a method of Link
you have to know what you are doing. You have to know what is the meaning of prev
and succ
, wether its the members of this
or another object. The method has to make sure that the invariants are not violated: After calling erase
the caller still has a valid Link
. And to do that you are dealing with implementation details: a valid Link
has prec
and a succ
.
Conclusion: Not being able to access private methods of other objects would be a major hurdle and not really bring an advantage (because anyhow while inside a method you are already dealing with implementation details of the class and you often do violate invariants temporarily).