返回介绍

31.3 封装

发布于 2025-02-22 14:00:51 字数 2395 浏览 0 评论 0 收藏 0

封装是一个把数据装在类的 private 域里面的动作,这样会让它们只能从类的内部被访问到,而从外面访问不到。 但是,生成的代码里面是否有什么东西指示一个变量是 private 呢? 没有,让我们看看简单的例子:

#include <stdio.h>
class box
{
private:
int color, width, height, depth;
public:
box(int color, int width, int height, int depth)
{
this->color=color;
this->width=width;
this->height=height;
this->depth=depth;
};
void dump()
{
printf ("this is box. color=%d, width=%d, height=%d, depth=%d
", color, width,
height, depth);
};
};

在 MSVC 2008+/Ox 和/Ob0 选项,然后看看 box::dump() 代码:

?dump@box@@QAEXXZ PROC ; box::dump, COMDAT
; _this$ = ecx
mov eax, DWORD PTR [ecx+12]
mov edx, DWORD PTR [ecx+8]
push eax
mov eax, DWORD PTR [ecx+4]
mov ecx, DWORD PTR [ecx]
push edx
push eax
push ecx
; ’this is box. color=%d, width=%d, height=%d, depth=%d’, 0aH, 00H
push OFFSET ??_C@_0DG@NCNGAADL@this?5is?5box?4?5color?$DN?$CFd?0?5width?$DN?$CFd?0@
call _printf
add esp, 20 ; 00000014H
ret 0
?dump@box@@QAEXXZ ENDP ; box::dump

这就是类的内存分布:

enter image description here

所有域都不允许其他类的访问,但是,我们知道这个存放方式之后是否可以修改这些域? 所以我加了 hack_oop_encapsulation() 函数,假设他有这个代码,当然我们没有编译:

void hack_oop_encapsulation(class box * o)
{
o->width=1; // that code can’t be compiled: "error C2248: ’box::width’ : cannot access
private member declared in class ’box’"
};

还有,如果要转换 box 的类型,把它从指针转为 int 数组,然后如果我们能修改这些数字,那么我们就成功了。

void hack_oop_encapsulation(class box * o)
{
unsigned int *ptr_to_object=reinterpret_cast<unsigned int*>(o);
ptr_to_object[1]=123;
};

这个函数的代码非常简单,剋说函数指示把指针指向这些 int,然后把 123 写入第二个 int:

?hack_oop_encapsulation@@YAXPAVbox@@@Z PROC ; hack_oop_encapsulation
mov eax, DWORD PTR _o$[esp-4]
mov DWORD PTR [eax+4], 123 ; 0000007bH
ret 0
?hack_oop_encapsulation@@YAXPAVbox@@@Z ENDP ; hack_oop_encapsulation

看看它是怎么工作的:

int main()
{
box b(1, 10, 20, 30);
b.dump();
hack_oop_encapsulation(&b);
b.dump();
return 0;
};

运行后:

this is box. color=1, width=10, height=20, depth=30
this is box. color=1, width=123, height=20, depth=30

可以看到,private 只是在编译阶段被保护了,c++编译器不会允许其他代码修改 private 域下的内容,但是如果用一些技巧,就可以修改 private 的值。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文