C++ 继承语义下构造函数中的对象指针 | 您所在的位置:网站首页 › 继承中的构造函数 › C++ 继承语义下构造函数中的对象指针 |
展示一段程序,对其做一些讨论。 1 #include 2 #include 3 using namespace std; 4 5 class X { 6 public: 7 X* ptr; 8 X() { 9 cout 16 (int (*)(...))X::func // slot for the first vfunc /* pseudo code * & : address-of, -> : member access through pointer */ X::X(this): // this is a pointer of type X* this->vptr = (& vtable for X) + 16 // (& this->vptr) : this + 0 print typeinfo::name(& typeinfo for X) // (& this->ptr) : this + 8 this->ptr = this在构造 y时,先将y的地址作为参数传给Y::Y(), 由 Y::Y() 来对其初始化。 Y::Y() 将y 中 X 子对象的初始化委托给了 X::X(), 最后再在Y::Y() 中对 vptr 赋值。 我这里说"赋值"是因为Y对象的地址与其X子对象的地址相同(这是最简单的情形,子对象地址的偏移值为 0),在X::X()中已经将vptr这个机器字初始化为X的第一个虚函数的在虚表中的位置,在 Y::Y() 中需要覆盖这个不合理的vptr值,将其设置为指向存在于Y的虚表中的第一个虚函数的位置。通过Y对象访问的ptr指针在调用Y::Y()后被初始化为其X子对象的地址,实际上也是Y对象的地址。 下面给出 Y 对象的内存布局、Y 类的虚表 和 Y::Y() 的伪代码: 1 Y object layout Vtable for Y 2 0 vptr ----------+ vtable for Y: 3u entries 3 8 ptr | 0 (int (*)(...))0 4 | 8 (int (*)(...))(& typeinfo for Y) 5 +-------> 16 (int (*)(...))Y::func 6 7 Y::Y(this): // this is a pointer of type Y* 8 X::X(this + 0) 9 this->vptr = (& vtable for Y) + 16 // (& this->vptr) : this + 0现在很容易知道 x.ptr->func() 和 y.ptr->func() 的输出是什么,这是每个C++程序员都熟悉的动态绑定。 x.ptr 和 y.ptr 均为类型为X*的指针,x.ptr 指向 x,y.ptr 指向y, 但他们调用 func() 时, 通过一致的表达式(在汇编语言中,是一致的命令序列)就可以实现多态, 这得益于基于虚指针和虚表的编译器实现。 体现汇编语言层面语义的伪代码: // pseudo code // *(ptr) : extract 8 bytes from the address pointed by ptr px = /* x.ptr or y.ptr */ vptr = *(px) // get the vptr pfunc = *(vptr) // get the function pointer pfunc(px) // call func()
|
CopyRight 2018-2019 实验室设备网 版权所有 |