Why do objects of the same class have access to each other's private data?
Asked Answered
M

7

121

Why do objects of the same class have access to each other's private data?

class TrivialClass {
public: 
  TrivialClass(const std::string& data) :
    mData(data) {};

  const std::string& getData(const TrivialClass& rhs) const {
    return rhs.mData;
  };

private:
  std::string mData;
};

int main() {
  TrivialClass a("fish");
  TrivialClass b("heads");

  std::cout << "b via a = " << a.getData(b) << std::endl;
  return 0;
}

This code works. It is perfectly possible for object a to access private data from object b and return it. Why should this be so? I would think that private data is private. (I started out by trying to understand copy constructors in the pimpl idiom, but then I discovered that I didn't even understand this simple situation.)

Magnet answered 3/8, 2011 at 3:0 Comment(6)
Well, as a starting point, you wouldn't be able to properly implement any copy-constructors for anything but the simplest classes. You can think of classes as being their own best friend :-)Trixi
Think of private from their customers, but all employees of the class have accessOiler
Thanks Cameron. That makes sense, but then why isn't this access restricted to only copy constructors and assignment operators?Magnet
Objects of the same type often interact a lot. And nobody is forcing you to write a method that hands out private data of another instance. :)Gecko
Simply because, at compile time, compiler has no way of identifying its the same object. Enforcing such access would require run-time support.Understudy
It is the job of the implementation of TrivialClass to understand how to properly manipulate TrivialClass::mData.Picayune
S
93

Because that's how it works in C++. In C++ access control works on per-class basis, not on per-object basis.

Access control in C++ is implemented as a static, compile-time feature. I think it is rather obvious that it is not really possible to implement any meaningful per-object access control at compile time. Only per-class control can be implemented that way.

Some hints of per-object control are present in protected access specification, which is why it even has its own dedicated chapter in the standard (11.5). But still any per-object features described there are rather rudimentary. Again, access control in C++ is meant to work on per-class basis.

Struve answered 3/8, 2011 at 3:26 Comment(5)
+1. C++ is big on compile-time mechanisms, not so big on run-time mechanisms. Pretty good general rule.Retail
Your "it is not really possible to implement any meaningful per-object access control at compile time". Why not? In void X::f(X&x), the compiler is easily capable of distinguishing this->a and x.a. It's not (always) possible for the compiler to know that *this and x are actually the same object if x.f(x) is invoked, but I could very well see a language designer find this OK.Beading
@AndréCaron I think this is actually a much larger of kettle of fish then you make it out to be. When inlining does not occur the compiler will always have to do a check whether this and &x are the same. To make it worse this actually ends up being an issue even with X::f(Y& y), because our concrete object could be of type Z that inherits from both X and Y. In short it's a real mess, not performant, hard to make work sensibly with MI.Candiot
@NirFriedman I think you misunderstand the suggestion. When compiling X::f(X& x), if there are accesses to x.a, it wouldn't compile. Nothing else changes, no checks need to be inserted, so performance of still-valid programs isn't affected. And it isn't suggested as a breaking change to existing C++, but as something that designers could have done when introducing private originally.Chivalrous
+1 @AlexeyRomanov. It sounds like compile-time checking of object instances is not a big issue, but other considerations raised in other answers to this question remain E.g. how to support copy operations.Fulgurate
A
35

"Private" isn't really an access control mechanism in the sense of "I made my pictures on facebook private so you can't see them."

In C++, "private" simply says these are parts of a class that you (the coder of the class) might change in future versions, etc., and you don't want other coders using your class to rely on their existence or functionality.

If you want true access control, you should implement genuine data security techniques.

Arc answered 3/8, 2011 at 3:29 Comment(0)
N
14

It's somewhat of an arbitrary language design decision. In Ruby, for instance, private really means private, as in "only the instance can access its own private data members". However, this is somewhat restrictive.

As pointed in the comments, copy constructors and assignment operators are common places where you access another instance's private data members directly. There are less obvious reasons why.

Consider the following case. You're implementing an OO linked-list. The linked-list has a nested node class for managing pointers. You might implement this node class such that it manages the pointers itself (rather than having the pointers public and managed by the list). In such a case, you'd have the node objects wanting to modify other node objects' pointers at other places that the typical copy constructor and assignment operator.

Navigator answered 3/8, 2011 at 3:28 Comment(0)
C
13

This is a good question and I have come across this question recently. I had some discussions with my colleagues and here is the summary of our discussion: This is by design. It doesn't mean this design is totally reasonable for all cases, but there must be some considerations why per class private is chosen. The possible reasons we could think of include:

First of all, the cost of per instance access control could be very high. This has been discussed by others in this thread. In theory, this can be done via this pointer check. However, this cannot be done at compilation time, and can only be done at run time. So you have to identify the access control of each member at run time, and when it's violated possibly only exceptions will be raised. The cost is high.

Secondly, per class access control has its own use case, like copy constructor or operator =. It would be difficult to implement them if access control is per instance.

Plus, the access control is mainly from programming/language perspective, for how to modularise/control the access to the code/member, not the data.

Cnidoblast answered 27/10, 2015 at 3:22 Comment(0)
M
6

The trick is to remember that the data is private to the class, not the instance of the class. Any method within your class can access the private data of any instance of that class; there's not a way to keep data private to within an instance unless you forbid methods that explicitly access private data members of other instances.

Macruran answered 3/8, 2011 at 3:29 Comment(0)
D
1

In addition to all the answers above, consider custom copy constructors, assignment operators and all the other functions you would write for a class which operate on other instances. You would need accessor functions for all those data members.

Desdamonna answered 15/11, 2017 at 16:52 Comment(0)
C
-9

Private data remains private until somebody who has access to it reveal it to other.

This concept applies to other situation too, such as :

class cMyClass
{
public:
   // ...
   // omitted for clarity
   // ...

   void Withdraw(int iAmount)
   {
      iTheSecretVault -= iAmount;
   }

private:
   int iTheSecretVault;
};

How could anyone withdraw the money ? :)

Criner answered 3/8, 2011 at 3:20 Comment(4)
This example does not involve one class instance accessing another instance's private data members.Beading
@Andre, "This concept applies to other situation too, such as..."Criner
^ "other situation" are off-topic by definition, so your example is of no relevance (and I'm not sure it would be informative anywhere else either)Gripper
This not at all correct explanation to the question.Mandibular

© 2022 - 2024 — McMap. All rights reserved.