这个c ++宏在做什么?

Abd*_*man 1 c++ macros

我不知道下面的宏在做什么?如果有人能帮助我看到它,将不胜感激.

#define BASE_OFFSET(ClassName,BaseName)\
(DWORD(static_cast < BaseName* >( reinterpret_cast\
< ClassName* >(Ox10000000)))-Ox10000000)
Run Code Online (Sandbox Code Playgroud)

如果有人想知道它来自哪里,它来自Don Box Book Essential COM的第3章,他正在使用接口表构建QueryInterface函数,上面的宏以某种方式用于查找指向接口vtable的指针该类的类,其中class是实现BaseName的ClassName,虽然我不知道它是如何做到的.

Sev*_*yev 7

它告诉编译器:"想象一下有一个ClassName对象在0x10000000.BaseName数据从那个对象开始到哪里,相对于0x10000000"?

想想具有多个基础的类对象的内存布局:

class A: B, C{};
Run Code Online (Sandbox Code Playgroud)

在构成A对象的内存块中,存在属于B的数据块,也是属于C的数据块,以及特定于A的数据.由于至少一个基数的数据不能是与作为整体的类实例的地址相同this,传递给不同方法的指针的数值需要变化.宏检索差异的值.

编辑:按照惯例,指向vtable的指针是具有虚函数的任何类中的第一个数据成员.因此,通过查找基础数据的地址,可以找到其vtable指针的地址.

现在,关于类型转换.通常,当你对指针进行类型转换时,操作在内部是微不足道的 - 地址的数值不依赖于它指向的类型; 数据类型的概念仅存在于C级别.但是有一个重要的例外 - 当您使用多重继承转换对象指针时.正如我们刚才所讨论的那样,this需要传递给基类方法的指针可能在数值上与派生对象的指针不同.

因此,static_cast和reinterpret_cast之间的区别巧妙地捕获了这种差异.当你使用reinterpret_cast时,你告诉编译器:"我知道的更好.取这个数值并将其解释为指向我所说的".这是故意颠覆类型系统,危险但偶尔也是必要的.根据定义,这种演员是微不足道的 - 因为你这么说.

"琐碎"我的意思是 - 指针的数值不会改变.

static_cast是一个更高级别的构造.在这种特殊情况下,您将在对象及其基础之间进行转换.根据C++类规则,这是一个合理的,安全的演员 - 但它可能在数值上是非常重要的.这就是宏使用两种不同类型转换的原因.static_cast不违反类型系统.

回顾一下:

reinterpret_cast<ClassName* >(OxlOOOOOOO)
Run Code Online (Sandbox Code Playgroud)

是一个不安全的操作.它返回一个虚假指针指向虚假对象,但它没关系,因为我们永远不会取消引用它.

static_cast<BaseName*>(...)
Run Code Online (Sandbox Code Playgroud)

是一个安全的操作(带有不安全的指针,具有讽刺意味).它是非平凡指针类型转换发生的部分.

(DWORD(...)-OxlOOOOOOO)
Run Code Online (Sandbox Code Playgroud)

是纯粹的算术.这就是不安全的原因:不再使用指针作为指针,我们将其转换为整数并忘记它曾经是指针.

最后一个阶段可以等同地改写为:

((char*)(...)-(char*)OxlOOOOOOO)
Run Code Online (Sandbox Code Playgroud)

如果这更有意义.