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 开发者_StackOverflow中文版simple situation.)
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.
"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.
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.
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.
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.
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.
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 ? :)
精彩评论