C++ Is private really private?

别来无恙 提交于 2019-12-04 22:40:02

private is not a security mechanism. It's a way of communicating intents and hiding information that other parts of your program do not need to know about, thus reducing overall complexity.

Having two different header files is not standards compliant, so technically you're entering undefined behaviour territory, but practically, as you've found, most compilers won't care.

You've strayed beyond what's allowed in C++, so what you're doing isn't allowed - but of course it may work on some compilers in some situations.

Specifically, you're violating the One Definition Rule.

This article by Herb Sutter explains it quite nicely - it also provides a legal and portable way of circumventing the access specifier system.

No. The private access control is there to stop YOU from doing stupid things, not as a security mechanism to stop others accessing your data or functions. There are many, many ways of getting around it.

I tried. This is an nm of a program I wrote having a class Test with one private method and a public one.

0000000100000dcc T __ZN4Test3barEv
0000000100000daa T __ZN4Test3fooEv

As you can see, the signature is exactly the same. The linker has absolutely nothing to distinguish a private method from a public one.

I agree with most of the other answers.

However, I'd like to point out that it is perfectly acceptable for a compiler to physically arrange the members differently when you remove that private. If it works, that is luck. You can't count on it. If both sides aren't using the same declaration, they aren't really using the same class.

There is no A::actualPrintX implementation anywhere. That is your linker error.

Since noone has mentioned a way to block this... One possible way to block access to private members, is to declare them as a separate internal type not visible outside the file. Of course, if you want to provide explicit access to this internal, you would then have to provide the internal declaration. That's also commonly done using an internal header containing that type.

Note: You'll have to keep track of allocating/freeing that internal object in this example. There are other ways of doing it that don't require this.

// class_A.h
class A {
public:
  void printX();
private:
  void *Private;
};

// class_A.cpp
class A_private {
  void actualPrintX();
  int x;
};

void A::printX() {
  reinterpret_cast<A_private *>(Private)->actualPrintX();
}

void A_private::actualPrintX() {
  std::cout << x:
}

In most cases you don't even have to edit header file to make private members public. You can do this with preprocesor. Something like this:

//"classWithPrivateMembers.hpp"
class C
{
private: //this is crucial for this method to work
    static int m;
};

int C::m = 12;

and then, this will work:

#define private public  
#include "classWithPrivateMembers.hpp"  
#undef private

int main()
{
    C::m = 34; // it works!
}

Bear in mind also that when you change a member variable's access, the compiler may place it at a different offset within the class object. The standard allows compilers a fair amount of freedom in rearranging members (at least within the same access level, I think).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!