是源自 C 语言的宏,它接受两个参数(类型名和成员名),返回一个 类型的常量表达式。 的返回值是成员在该类型对象中以字节计算的的偏移量。其中,传入计算的类型名,必须满足标准内存布局的要求;即
- 所有非 数据成员的访问控制权限相同;
- 没有虚函数;
- 不从虚基类继承;
- 所有非 数据成员都不是引用类型;
- 所有非 数据成员类型和基类都满足上述要求。
若传入计算的类型名不满足内存布局的要求,或者求解的成员是 成员或成员函数,则调用该宏是未定义行为(Undefined Behaviour)。
按照定义,有
- 的值只与类型和成员有关,也就是说,在计算 的时候,不应传入 类型具体某个对象,也不应为计算该值而临时构造一个对象;
- 的值,其单位是字节;
- 的值应是 类型。
的这三个特性,也是实现 宏的三个难点。为了解决这些问题,首先,实现应当让编译器相信在某处存在一个「虚拟的」但是「可用的」对象。而后,根据该虚拟对象,可以取得目标成员 的地址。随后,利用 的地址与该虚拟对象的起始地址做差,即可得知 的偏移量;为了求得以字节为单位的 ,需将 的地址转变为 类型的指针。最后,只需将 转换为 即可。
因此,有如下 C++ 实现:
此处,通过 ,编译器相信在 处()有一个真实存在的 类型的对象。此处使用 而非 是因为 C++ 标准不允许将 通过 转换成其他类型的指针;此类转换应用 。由于 返回指向 类型对象的指针,因此 就是一个虚拟但在编译器看来可用的成员变量 。为了求得以字节为单位的 ,实现中通过 获得一个 类型的变量。由于在该实现中,虚拟的变量位于 位置,故而 即是 在 类型对象当中相对对象起始地址的偏移量。最后,只需将它转换为 类型的值即可:。
同样,可以有 C 风格的实现:
上述测试代码的结果是:
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/12855.html