c++ - 为什么 C++ 允许使用这种方法修改私有(private)成员?

标签 c++ private-members

看完后this question 几分钟前,我想知道为什么语言设计者允许它,因为它允许间接修改私有(private)数据。举个例子

 class TestClass {
   private:
    int cc;
   public:
     TestClass(int i) : cc(i) {};
 };

 TestClass cc(5);
 int* pp = (int*)&cc;
 *pp = 70;             // private member has been modified

我测试了上面的代码,确实修改了私有(private)数据。是否有任何解释为什么允许这种情况发生,或者这只是语言中的疏忽?它似乎直接破坏了私有(private)数据成员的使用。

最佳答案

因为,正如 Bjarne 所说,C++ 旨在防止 Murphy,而不是 Machiavelli。

换句话说,它应该可以保护您免受事故的影响——但是如果您从事任何破坏它的工作(例如使用类型转换),它甚至不会试图阻止您。

当我想到它时,我想到了一个有点不同的比喻:它就像浴室门上的锁。它向您发出警告,表明您现在可能不想走进去,但如果您决定从外面打开门,那是微不足道的。

编辑:至于@Xeo 讨论的问题,关于为什么标准说“拥有相同的访问控制”而不是“拥有所有公共(public)访问控制”,答案很长而且有点曲折。

让我们回到开始,考虑一个像这样的结构:

struct X {
    int a;
    int b;
};

对于这样的结构,C 总是有一些规则。一种是在结构体的实例中,结构体本身的地址必须等于a的地址。 ,因此您可以将指向结构的指针转换为指向 int 的指针。 , 并访问 a具有明确的结果。另一个是成员在内存中的排列顺序与它们在结构中定义的顺序相同(尽管编译器可以自由地在它们之间插入填充)。

对于 C++,有意维护这一点,尤其是对于现有的 C 结构。同时,如果编译器想要强制执行 private,有一个明显的意图。 (和 protected )在运行时,应该很容易做到(合理有效)。

因此,给出类似的东西:
struct Y { 
    int a;
    int b;
private:
    int c;
    int d;
public:
    int e;

    // code to use `c` and `d` goes here.
};

应该要求编译器在 Y.a 方面保持与 C 相同的规则。和 Y.b .同时,如果它要在运行时强制访问,它可能希望将所有公共(public)变量一起移动到内存中,因此布局更像是:
struct Z { 
    int a;
    int b;
    int e;
private:
    int c;
    int d;
    // code to use `c` and `d` goes here.
};

然后,当它在运行时强制执行时,它基本上可以执行类似 if (offset > 3 * sizeof(int)) access_violation(); 的操作。

据我所知,没有人做过这件事,我不确定标准的其余部分是否真的允许这样做,但似乎至少有一个想法的半成形胚芽沿着这条线。

为了强制执行这两者,C++98 说 Y::aY::b必须按照内存中的顺序,并且 Y::a必须在结构的开头(即类似 C 的规则)。但是,由于中间的访问说明符,Y::cY::e彼此之间不再需要井然有序。换句话说,所有在它们之间没有访问说明符定义的连续变量被分组在一起,编译器可以自由地重新排列这些组(但仍然必须在开始时保留第一个)。

这很好,直到某个 SCSS (即我)指出规则的编写方式还有一个小问题。如果我写的代码如下:
struct A { 
    int a;
public:
    int b;
public:
    int c;
public:
    int d;
};

......你最终有点自相矛盾。一方面,这仍然是正式的 POD 结构,因此应该应用类似 C 的规则——但是由于您在成员之间拥有(不可否认的无意义)访问说明符,它还允许编译器重新排列成员,因此打破他们想要的类似 C 的规则。

为了解决这个问题,他们对标准进行了一些重新措辞,以便讨论所有成员都具有相同的访问权限,而不是他们之间是否存在访问说明符。是的,他们本可以刚刚宣布规则仅适用于公共(public)成员,但似乎没有人认为可以从中获得任何好处。鉴于这是修改现有标准,其中包含大量已使用了很长时间的代码,因此选择了他们可以进行的最小更改仍然可以解决问题。

关于c++ - 为什么 C++ 允许使用这种方法修改私有(private)成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12093319/

相关文章:

c++ - c++中隐藏特定函数的一种方法

c++ - sizeof 运算符生成的数据类型

c++ - 使用 Rcpp 进行高效矩阵子集化

java - 通过 Java 中的反射访问私有(private)继承字段

apache-flex - 弹性 : How do you list private attributes of a class?

.net - MSIL - 如何从 MSIL 调用私有(private)方法?

c++ - 如何在 std::map 中插入自定义对象

c++ - 如何在结构中将值传递给std::optional?

c++ - 如何在 Qt C++ 应用程序中显示带有大量小部件的可滚动列表作为项目?

unit-testing - 使用 Moq 验证私有(private)方法的执行