BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #47462同步于 2010/12/7
CPP机器人发帖

[合集] 如何强制访问c++私有成员

shenlei
2010/12/7镜像同步0 回复
☆─────────────────────────────────────☆ Livy (Livy) 于 (Tue Nov 4 20:45:56 2008) 提到: 前几天笔试adobe,出了这样一个题,当时只想到通过指针的偏移量来访问,但是由于对C++的类对象布局不是很有把握,就随便写了个答案,今天上百度搜了下,发现好几种方法,拿出来一起分享。 先看一个类 #include <stdio.h> class A { private: char *str; public: A(): str("nothing"){}; }; int main() { A a; return 0; } 如何输出a的私有成员str所指向的字符串"nothing"?可以任意添加代码,但不可以修改这个类。 ★★方法一: 在定义A前,加一句“#define private public”。该方法可以欺骗编译器,让它把“private”当作“public”,然后就可以用“a.str”了。 达到了我们的目的,只可惜这个方法有点“左道旁门”。 ★★方法二: a.str的地址就是a的地址,所以用“puts(*(char**)&a);”即可访问a.str。 ★方法二变种: 方法二不错,但如果str不是类的第一个成员变量,就会有点麻烦。比如,把A改成如下形式: class A { private: char d; char *str; public: A(): str("nothing"){}; }; d占一个字节,a.str的地址相对于a的地址,偏移量为1,可以这么用“puts(*(char**)((char*)&a+1));”。这看似不错,但没有考虑字节对齐 问题。为了能高效的访问变量,编译器可能会以空间换时间,采取字节对齐措施。字节对齐后,程序高效了,但对我们而言就麻烦了。str的地 址的偏移量未必是1,可以是2、4、8等,怎么才能获取a.str的偏移量呢?别急,我们可以给该方法打打补丁。 ☆方法二变种的补丁: 在定义A前,加一句“#pragma pack(1)”,这行代码可以让编译器按1字节进行对齐,这样以后就可以放心大胆地用“puts(*(char**)(char*) &a+1));”了。 ★★方法三: 方法二的变种打了补丁后,也有了“左道旁门”的“嫌疑”。方法三就显得“高尚”多了。构造一个和A相似的类,但增加了一个非虚成员函数 ,用来返回str的地址。 #include <stdio.h> class A { private: char *str; public: A(): str("nothing"){}; }; class B { private: char *str; public: B(): str("nothing"){}; char *get() { return str; } }; int main() { A a; puts(((B*)(&a))->get()); return 0; } ★★方法四: 和方法三一样,也是构造一个新的类。但有所不同的是,“private”变成了“public”。B的布局和A相同,即同名变量的偏移量相同。这样, 我们就可以把A实例的指针转化为B*类型,来访问str了。 #include <stdio.h> class A { private: char *str; public: A(): str("nothing"){}; }; class B { public: char *str; public: B(): str("nothing"){}; }; int main() { A a; //或“puts(((B*)(&a))->str);” puts(reinterpret_cast<B*>(&a)->str); return 0; } ☆─────────────────────────────────────☆ purevirtual (天之健|杨无敌|hf) 于 (Tue Nov 4 20:52:08 2008) 提到: 版上有这个帖子,最简单的方法是struct 【 在 Livy (Livy) 的大作中提到: 】 : 前几天笔试adobe,出了这样一个题,当时只想到通过指针的偏移量来访问,但是由于对C++的类对象布局不是很有把握,就随便写了个答案,今天上百度搜了下,发现好几种方法,拿出来一起分享。 : 先看一个类 : #include <stdio.h> : ................... ☆─────────────────────────────────────☆ Livy (Livy) 于 (Tue Nov 4 21:02:25 2008) 提到: 【 在 purevirtual 的大作中提到: 】 : 版上有这个帖子,最简单的方法是struct 没明白如何用struct实现 ☆─────────────────────────────────────☆ purevirtual (天之健|杨无敌|hf) 于 (Tue Nov 4 21:03:51 2008) 提到: 你版面搜索一下 这个一点不就清楚了 定义一个struct == class ,里面的成员函数和数据都是一样的,然后把class强转成struct不就可以了 【 在 Livy (Livy) 的大作中提到: 】 : 没明白如何用struct实现 ☆─────────────────────────────────────☆ Livy (Livy) 于 (Tue Nov 4 21:28:51 2008) 提到: 【 在 purevirtual 的大作中提到: 】 : 你版面搜索一下 这个一点不就清楚了 定义一个struct == class ,里面的成员函数和数据都是一样的,然后把class强转成struct不就可以了 明白了,呵呵,原来有这么多方法 ☆─────────────────────────────────────☆ jokerlee (Jackal The Dire) 于 (Wed Nov 5 12:28:37 2008) 提到: 我怎么觉得用个友元函数就行了,没必要这么旁门左道啊 ☆─────────────────────────────────────☆ ericyosho (ericyosho) 于 (Wed Nov 5 12:47:21 2008) 提到: 关键是,你不能修改原来类的实现啊。 用友员达不到这个要求。 【 在 jokerlee 的大作中提到: 】 : 我怎么觉得用个友元函数就行了,没必要这么旁门左道啊 ☆─────────────────────────────────────☆ jokerlee (Jackal The Dire) 于 (Wed Nov 5 12:51:58 2008) 提到: 友元函数可以定义在外面 ☆─────────────────────────────────────☆ ny (ttmdy) 于 (Wed Nov 5 13:25:30 2008) 提到: 那怎么声明呢?某个类的友元函数是要在类里面声明的吧 【 在 jokerlee 的大作中提到: 】 : 友元函数可以定义在外面 ☆─────────────────────────────────────☆ hyang1985 (hyang1985) 于 (Fri Nov 7 10:25:54 2008) 提到: 在类里面声明,在外面定义 【 在 ny 的大作中提到: 】 : 那怎么声明呢?某个类的友元函数是要在类里面声明的吧 ☆─────────────────────────────────────☆ ys912 (nereus) 于 (Fri Nov 7 11:00:20 2008) 提到: puts(*(char**)&a) 为什么用puts((char*)&a)不行,谁能解释下? ☆─────────────────────────────────────☆ Livy (Livy) 于 (Fri Nov 7 11:28:53 2008) 提到: 【 在 ys912 的大作中提到: 】 : puts(*(char**)&a) : 为什么用puts((char*)&a)不行,谁能解释下? a里面的str本来就是一个char*类型的,a的地址和a中成员str的地址同一个地址,这样&a相当于char** [upload=1][/upload]
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。