Chinaunix首页 | 论坛 | 博客
  • 博客访问: 531807
  • 博文数量: 104
  • 博客积分: 2089
  • 博客等级: 大尉
  • 技术积分: 1691
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-29 08:48
文章分类

全部博文(104)

文章存档

2015年(1)

2013年(13)

2012年(31)

2011年(59)

分类: C/C++

2011-12-08 14:50:27

成员(member_name)在类(typen_ame)中的偏移:
  1. (int)(&((type_name*)NULL)->member_name)
例如有个类 A
  1. class A
  2. {
  3. public:
  4.     virtual int show() {}
  5.     int i1, i2;
  6. };
则 (int)(&((A*)NULL)->i2) == 8   
类地址+8的偏移处为i2的地址(4字节vmt表地址,4字节i1,所以i2的寻址偏移为8)

这样就能在属性类中自己计算出拥有属性类的类的地址了,这是因为类的寻址方式决定的,如下所示:
  1. class Child
  2. {
  3. public:
  4.   int i1, i2; i1偏移为0, i2为4,无vmt表
  5. };

  6. class Parent
  7. {
  8. public:
  9.    int i; i偏移为0
  10.    Child *c; c偏移为4
  11.    Parnet() {...} c的new 和 delete就不写了
  12. };
  13. Parent *p;
这时要new一个Parent类时,会在堆上分配二块内存,一块为c对象占用内存,一块为p对象占用内存.
要寻址类P对象中c对象的i2成员(p->c->i2),大概的汇编代码如下:
  1. mov ecx, p //得到p的指针
  2. mov ecx, [ecx + 4] //得到p对象成员c的指针
  3. mov eax, [ecx + 4] //得到c对象成员i2的地址
这样就寻址到了i2

但如果Parent类不是包含的Child类的指针,而是直接包含的对象,情况就不一样了,如下:
  1. class Parent
  2. {
  3. public:
  4.    int i; i偏移为0
  5.    Child c; c偏移为4(注意不同,这里c不是Child*)
  6. };
  7. Parent *p;
这时要new一个Parent类时,只会在堆上分配一块内存,为p对象占用内存,c对象包含在p对象内,直接使用p对象的内存,要寻址类P对象中c对象的i2成员(p->c.i2),大概的汇编代码如下:
  1. mov ecx, p //得到p的指针
  2. mov ecx, ecx + 8 //得到i2的地址 8 = c偏移+i2在c类中的偏移,编译优化
要寻址类P对象中c对象的地址,如下:
  1. mov ecx, p //得到p的指针
  2. mov ecx, ecx + 4 //得到c的地址 p对象指针+偏移
从上面可以看出,只要知道c类地址,要得到p的指针,就 c地址 - c对象在p对象中的偏移就行了.
事情就简单了,示例代码如下:
  1. #include <iostream>

  2. using std::cout;
  3. using std::cin;
  4. using std::endl;

  5. template<typename T, typename int(*GetOffset)()>
  6. class Property
  7. {
  8. public:
  9.     Property()
  10.     {
  11.         cout << "this:" << (int)this << std::endl;
  12.         cout << "owner:" << (int)this - GetOffset() << std::endl;
  13.     }
  14. };

  15. #define PROPERTY_DECLARE(pro_name, type_name)/
  16.     private: int inline static pro_name##_offset() {return (int)(&((type_name*)NULL)->pro_name);};/
  17.     public: Property<type_name, type_name::pro_name##_offset> pro_name;

  18. class PropertyTest
  19. {
  20. public:
  21.     int i;
  22. public:
  23.     PROPERTY_DECLARE(Name, PropertyTest)
  24. };

  25. int main()
  26. {
  27.     PropertyTest *test = new PropertyTest();
  28.     cout << std::endl;
  29.     cout << "property address:" << (int)(&test->Name) << std::endl;
  30.     cout << "test class address:" << (int)test << std::endl;

  31.     std::cin.get();
  32.     return 0;
  33. }

----------------------
这是摘抄的文章,挺有意思,以后完善。

引用:
http://blog.csdn.net/pankun/article/details/598582


阅读(1364) | 评论(0) | 转发(0) |
0

上一篇:C++ template

下一篇:C++ 可以多个函数声明

给主人留下些什么吧!~~