C++私人真的是私人的吗?
我正在尝试 C++ 中 private
访问说明符的有效性。这里是:
接口:
// class_A.h
class A
{
public:
void printX();
private:
void actualPrintX();
int x;
};
实现:
// class_A.cpp
void A::printX()
{
actualPrintX();
}
void A::actualPrintX()
{
std::cout << x:
}
我将其内置到静态库(.a/.lib)中。我们现在有一个 class_A.h 和 classA.a(或 classA.lib)对。 我编辑了 class_A.h 并从中删除了 private:
。
现在在另一个 classTester.cpp 中:
#include "class_A.h" // the newly edited header
int main()
{
A a;
a.x = 12; // both G++ and VC++ allowed this!
a.printX(); // allowed, as expected
a.actualPrintX(); // allowed by G++, VC++ gave a unresolved linker error
return 0;
}
我知道在篡改库的标头后,所有的赌注都消失了(我的意思是,系统完整性等)虽然方法很hacky,但这真的允许吗?有办法阻止这个吗?或者我在这里做错了什么?
I was trying out the validity of private
access specifier in C++. Here goes:
Interface:
// class_A.h
class A
{
public:
void printX();
private:
void actualPrintX();
int x;
};
Implementation:
// class_A.cpp
void A::printX()
{
actualPrintX();
}
void A::actualPrintX()
{
std::cout << x:
}
I built this in to a static library (.a/.lib). We now have a class_A.h and classA.a (or classA.lib) pair. I edited class_A.h and removed the private:
from it.
Now in another classTester.cpp:
#include "class_A.h" // the newly edited header
int main()
{
A a;
a.x = 12; // both G++ and VC++ allowed this!
a.printX(); // allowed, as expected
a.actualPrintX(); // allowed by G++, VC++ gave a unresolved linker error
return 0;
}
I know that after tampering a library's header all bets are off (I mean, system integrity, etc.) Albeit the method being hacky, is this really allowed? Is there a way to block this? Or am I doing something wrong here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
private
不是一种安全机制。这是一种传达意图并隐藏程序其他部分不需要了解的信息的方式,从而降低整体复杂性。拥有两个不同的头文件不符合标准,因此从技术上讲,您正在进入未定义的行为领域,但实际上,正如您所发现的,大多数编译器都不会关心。
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.
你已经超出了 C++ 允许的范围,所以你所做的事情是不允许的 - 但当然它可能在某些情况下在某些编译器上工作。
具体来说,您违反了单一定义规则。
Herb Sutter 的这篇文章很好地解释了这一点 - 它还提供了一种合法且可移植的方式规避访问说明符系统。
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.
我试过。这是我编写的一个程序的一个 nm,它有一个带有一个私有方法和一个公共方法的 Test 类。
正如您所看到的,签名完全相同。链接器完全无法区分私有方法和公共方法。
I tried. This is an nm of a program I wrote having a class Test with one private method and a public one.
As you can see, the signature is exactly the same. The linker has absolutely nothing to distinguish a private method from a public one.
我同意大多数其他答案。
不过,我想指出,当您删除该
private
时,编译器以不同的方式物理排列成员是完全可以接受的。如果有效的话,那就是运气了。你不能指望它。如果双方没有使用相同的声明,那么他们实际上并没有使用同一个类。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.由于没有人提到阻止这种情况的方法...阻止访问私有成员的一种可能方法是将它们声明为在文件外部不可见的单独内部类型。当然,如果您想提供对此内部的显式访问,则必须提供内部声明。这通常也是使用包含该类型的内部标头来完成的。
注意:在此示例中,您必须跟踪分配/释放该内部对象。还有其他不需要这样做的方法。
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.
任何地方都没有 A::actualPrintX 实现。那是你的链接器错误。
There is no A::actualPrintX implementation anywhere. That is your linker error.
在大多数情况下,您甚至不必编辑头文件即可将私有成员设为公开。您可以使用预处理器来完成此操作。像这样:
然后,这将起作用:
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:
and then, this will work:
还要记住,当您更改成员变量的访问权限时,编译器可能会将其放置在类对象中的不同偏移处。该标准允许编译器在重新排列成员方面有相当大的自由度(我认为至少在相同的访问级别内)。
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).