C++私有真的是私有的吗?

leg*_*s2k 18 c++ encapsulation private data-integrity access-specifier

private在C++中尝试访问说明符的有效性.开始:

接口:

// class_A.h

class A
{
public:
    void printX();
private:
    void actualPrintX();
    int x;
};
Run Code Online (Sandbox Code Playgroud)

执行:

// class_A.cpp
void A::printX()
{
    actualPrintX();
}

void A::actualPrintX()
{
    std::cout << x:
}
Run Code Online (Sandbox Code Playgroud)

我将其构建到静态库(.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;
}
Run Code Online (Sandbox Code Playgroud)

我知道在篡改了一个库的标题之后所有的赌注都没有了(我的意思是,系统完整性等等)虽然方法很黑,但这真的允许吗?有办法阻止这个吗?或者我在这里做错了什么?

Pon*_*gge 30

private不是一种安全机制.这是一种沟通意图和隐藏信息的方式,程序的其他部分不需要知道,从而降低整体复杂性.

有两个不同的头文件不符合标准,所以从技术上讲,你进入未定义的行为领域,但实际上,正如你所发现的,大多数编译器都不会关心.


Joe*_*oeG 9

你已经偏离了C++允许的范围,所以你所做的事情是不被允许的 - 当然它在某些情况下可能适用于某些编译器.

具体来说,您违反了" 一个定义规则".

Herb Sutter的这篇文章很好地解释了它 - 它还提供了一种绕过访问说明符系统的合法且可移植的方法.

  • 你已经两次定义了'class A` - 一次在`classTester.cpp`翻译单元中,一次在`class_A.cpp`翻译单元中.ODR违规是这两个定义不是一致的. (2认同)

小智 7

不可以.私人访问控制可以阻止您做愚蠢的事情,而不是阻止其他人访问您的数据或功能的安全机制.有许多方法可以绕过它.


Ste*_*ini 5

我试过了.这是我编写的一个程序的nm,它有一个使用一个私有方法和一个公共方法的类Test.

0000000100000dcc T __ZN4Test3barEv
0000000100000daa T __ZN4Test3fooEv
Run Code Online (Sandbox Code Playgroud)

如您所见,签名完全相同.链接器绝对没有区分私有方法和公共方法.


T.E*_*.D. 5

我同意大多数其他答案.

但是,我想指出,当你删除它时,编译器以不同的方式物理排列成员是完全可以接受的private.如果它有效,那就是运气.你不能指望它.如果双方都没有使用相同的声明,那么他们并没有真正使用同一个类.