我阅读了BRUCE ECKEL在C ++中思考的以下陈述
1.访问说明符是结构的一部分,不影响对象
创建
从“结构
怀疑:我们知道访问块不是连续存储的, 不知道访问说明符会改变内存中对象布局的方式
2.所有访问规范信息在程序运行之前消失 (在编译期间)。在正在运行的程序中,对象成为“存储区域”
而且没有更多..我们可以打破所有规则并直接访问内存 你可以在c
怀疑:这是否意味着甚至可以直接访问私人会员?请帮助我理解上述陈述
3.c ++设计是务实的,而不是渴望抽象交易
怀疑:什么是务实的意思?
答案 0 :(得分:8)
1)访问说明符是结构的一部分,不影响从“结构”
创建的对象
实际上,在相同的特定访问权限(public
,protected
或private
)内的数据成员的顺序(在布局中)取决于他们在代码中的顺序,但是没有为具有不同说明符的数据成员指定顺序。
class Foo
{
public:
int a;
int b;
protected:
int c;
int d;
};
我们唯一知道的是a
必须在b
和c
必须在d
之前到来。 abcd
,acbd
,acdb
,cabd
,cadb
和cdab
都是可能的。
2)所有访问规范信息在程序运行之前消失 (在编译期间)。在正在运行的程序中,对象成为“存储区域” 而且没有更多..因此我们可以打破所有规则并直接访问内存 你可以在c
该信息仅在编译期间使用,但编译是生成运行代码的原因。因此,编译可确保您不会访问private
成员。但是,由于允许直接内存操作,如果您愿意,可以有效地访问private
成员或函数,尝试手动执行此操作非常容易出错。
3)C ++旨在务实,而不是渴望抽象真实的
务实意味着它面向实际使用,很少考虑纯粹的理论论证。从CS理论构建的语言将包括例如Haskell,其具有极其合理的数学背景;另一方面,C ++积累了一些被用户认为有用的功能。
此外,C ++不会隐藏您的低级细节(如内存管理)。好的C ++代码通常会让编程器使用习惯用法来尝试抽象它(有点),但如果有必要,你可以随时更接近金属(甚至直接包括汇编代码)......有时候(比如内存管理)你必须要注意你正在做的事情。
答案 1 :(得分:1)
class Foo {
int x, y;
public:
int z;
Foo(int a, int b) : x(a), y(b) {}
};
Foo foo;
您可以非常轻松地访问私有成员变量:
memset(&foo, int 0, sizeof(foo)); // wipes them all
fwrite(&foo, sizeof(foo), 1, fp); // dumps them to stream fp
正如一些评论者指出的那样,这引发了C ++标准下的未定义行为,所以在尝试之前要知道你的编译器(或者更好,不要)。如果您知道编译器如何打包类,您甚至可以通过诸如
之类的黑客获得更细粒度的访问struct PublicFoo {
int x, y, z; // order, padding, etc. depends on compiler
};
并将Foo *
投射到PublicFoo *
。 C ++运行时中没有任何内容可以阻止它。