这几个 offset 是:
c 中的 offsetof 宏;
《COM本质论》: "inttable.h" 中的 BASE_OFFSET ;
和 This() (它用到了 offsetof,权且当做是一个 packaged offset 吧)。
先定义一些辅助类:
struct IX {
virtual void fx() = 0;
};
struct IY {
virtual void fy() = 0;
};
class CA : public IX,
public IY {
public:
virtual void fx() { cout << "CA::fx()" << endl; };
virtual void fy() { cout << "CA::fy()" << endl; };
struct Inner {
CA* This() { return (CA*)((char*)this - offsetof(CA, m_inner)); }
};
Inner m_inner;
};
先看 offsetof :
#define offsetof(s,m) (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
工作原理大体同下图所示,其值就是 a – 0 = a ,即 m 被映射后的地址。所以一个 –> 操作就可以搞定。
再看 BASE_OFFSET :
#define BASE_OFFSET(ClassName, BaseName) \
(DWORD(static_cast<BaseName*>(reinterpret_cast<ClassName*>(0x10000000))) - 0x10000000)
对于先前的定义,有:
DWORD disX = BASE_OFFSET(CA, IX);
DWORD disY = BASE_OFFSET(CA, IY);
cout << disX << endl // 0
<< disY << endl; // 4
这个宏主要利用了派生类指针到基类指针的转换,这一切由语言内置的转换符完成。在 ATL 中相应的定义是:
#define offsetofclass(base, derived) ((DWORD_PTR)(static_cast<base*>((derived*)_ATL_PACKING))-_ATL_PACKING)
其中 _ATL_PACKING 的值为 8 。为什么使用这两个值呢,我不知道。网上有说是为了避免 NULL 指针和负值,我暂时不能够理解。
最后来看 This() :
CA* This() { return (CA*)((BYTE*)this - offsetof(CA, Inner)); }
This() 返回的即是指向 CA 的指针,如: ca.m_inner.This()->fx(); 有了上面两个 offset ,这个就不难理解了。
整理完毕。
posted on 2009-12-12 15:16
崇文 阅读(405)
评论(0) 编辑 收藏 引用