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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (67)

我想知道为什么语言设计人员允许使用它,因为它允许对私有数据进行间接修改。作为一个例子

 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

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

提问于
用户回答回答于

因为C的反向可压缩性,所以你可以做同样的事情。

首先,TestClass标准布局类

  • 没有非标准布局类(或此类类型的数组)或引用的非静态数据成员,//OK:非静态数据成员类型为int
  • 没有虚拟函数(10.3)和虚拟基类(10.1),//确定
  • 对所有非静态数据成员具有相同的访问控制(第11条),//OK,所有非静态数据成员(1)都是“私有”成员。
  • 没有非标准布局基类,//OK,没有基类
  • 或者在大多数派生类中没有非静态数据成员,最多有一个具有非静态数据成员的基类,或者没有具有非静态数据成员的基类,并且//OK,再次没有基类
  • 没有与第一个非静态数据成员相同类型的基类。//OK,再次没有基类
用户回答回答于

考虑一下这样的结构:

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.
};

应该要求编译器维护与C在以下方面的相同规则:Y.aY.b同时,如果要在运行时强制访问,则可能希望将内存中的所有公共变量一起移动,因此布局更类似于:

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();

如果我写的代码如下:

struct A { 
    int a;
public:
    int b;
public:
    int c;
public:
    int d;
};

一方面,这仍然是一个正式的POD结构,所以C类规则应该适用--但是由于在成员之间有(诚然是没有意义的)访问说明符,它还允许编译器重新排列成员,从而破坏了它们想要的C类规则。

为了解决这一问题,他们稍微修改了标准,这样就可以讨论所有成员都有相同的访问权限,而不是他们之间是否存在访问说明符。

扫码关注云+社区

领取腾讯云代金券