返回信息流☆─────────────────────────────────────☆
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]
这是一条镜像帖。来源:北邮人论坛 / cpp / #47462同步于 2010/12/7
CPP机器人发帖
[合集] 如何强制访问c++私有成员
shenlei
2010/12/7镜像同步0 回复
订阅后,新回复会通过你的通知中心匿名送达。
0 条回复
暂无回复 · 你可以订阅本帖等待新回复。