因为,正如 Bjarne 所说,C++ 旨在防止墨菲,而不是马基雅维利。
换句话说,它应该保护你免受意外——但如果你去任何工作来破坏它(比如使用演员),它甚至不会试图阻止你。
当我想到它时,我想到了一个有点不同的类比:它就像浴室门上的锁。它会警告您,您现在可能不想走进那里,但是如果您决定从外面解锁门,那是微不足道的。
编辑:关于@Xeo 讨论的问题,关于为什么标准说“拥有相同的访问控制”而不是“拥有所有公共访问控制”,答案很长而且有点曲折。
让我们回到开头,考虑如下结构:
struct X {
int a;
int b;
};
对于这样的结构,C 总是有一些规则。一种是在结构的实例中,结构本身的地址必须等于 的地址a
,因此您可以将指向该结构的指针转换为指向 的指针int
,并a
以明确定义的结果进行访问。另一个是成员在内存中的排列顺序必须与它们在结构中定义的顺序相同(尽管编译器可以自由地在它们之间插入填充)。
对于 C++,有维护这一点的意图,尤其是对于现有的 C 结构。同时,有一个明显的意图是,如果编译器想要在运行时强制执行private
(and 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.a
规则Y.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();
据我所知,从来没有人这样做过,而且我不确定标准的其余部分是否真的允许这样做,但似乎至少有一个想法的半成形胚芽沿着这条线。
为了强制执行这两个,C++98 说Y::a
并且Y::b
必须在内存中按照这个顺序,并且Y::a
必须在结构的开头(即,类似 C 的规则)。但是,由于介入了访问说明符,Y::c
并且Y::e
不再必须是相对于彼此的顺序。换句话说,所有在它们之间没有访问说明符的连续变量都被组合在一起,编译器可以自由地重新排列这些组(但仍然必须将第一个变量保留在开头)。
这很好,直到某个混蛋(即我)指出规则的编写方式还有另一个小问题。如果我编写如下代码:
struct A {
int a;
public:
int b;
public:
int c;
public:
int d;
};
...你最终有点自相矛盾。一方面,这仍然是正式的 POD 结构,因此应该适用类似 C 的规则——但由于您在成员之间有(诚然没有意义的)访问说明符,它还允许编译器重新排列成员,因此打破了他们想要的 C 类规则。
为了解决这个问题,他们稍微重新措辞了标准,这样它就会谈论所有成员都具有相同的访问权限,而不是关于他们之间是否存在访问说明符。是的,他们本可以下令这些规则只适用于公共成员,但似乎没有人认为可以从中获得任何好处。鉴于这是在修改现有标准,其中包含大量已经使用了很长时间的代码,因此他们选择了他们可以做出的最小更改,但仍然可以解决问题。