我正在阅读这篇文章 "虚函数表"
在上述文章中的示例:
class B1 {
public:
void f0() {}
virtual void f1() {}
int int_in_b1;
};
class B2 {
public:
virtual void f2() {}
int int_in_b2;
};
class D : public B1, public B2 {
public:
void d() {}
void f2() {} // override B2::f2()
int int_in_d;
};
B2 *b2 = new B2();
D *d = new D();
在这篇文章中,作者介绍了对象
d
的内存布局如下: d:
D* d--> +0: pointer to virtual method table of D (for B1)
+4: value of int_in_b1
B2* b2--> +8: pointer to virtual method table of D (for B2)
+12: value of int_in_b2
+16: value of int_in_d
Total size: 20 Bytes.
virtual method table of D (for B1):
+0: B1::f1() // B1::f1() is not overridden
virtual method table of D (for B2):
+0: D::f2() // B2::f2() is overridden by D::f2()
这个问题涉及到
d->f2()
。调用 d->f2()
时将一个 B2
指针作为 this
指针传递,因此我们需要进行类似以下的操作:(*(*(d[+8]/*pointer to virtual method table of D (for B2)*/)[0]))(d+8) /* Call d->f2() */
为什么我们应该将
B2
指针作为this
指针传递,而不是原始的D
指针???实际上,我们正在调用D :: f2()。根据我的理解,在D :: f2()函数中,我们应该传递一个D
指针作为this
。___更新___
如果将一个
B2
指针作为this
传递给D::f2(),那么如果我们想要访问B1
类的成员怎么办?我相信B2
指针(this)就像这样: d:
D* d--> +0: pointer to virtual method table of D (for B1)
+4: value of int_in_b1
B2* b2--> +8: pointer to virtual method table of D (for B2)
+12: value of int_in_b2
+16: value of int_in_d
这个连续的内存布局已经有了一定的起始地址偏移量。例如,我们想在D :: f2()内部访问b1
,我想在运行时,它会执行类似于:*(this+4)
(this
指向与b2相同的地址),这将指向B
中的b2
吗?
B2
的指针作为this
传递给D::f2(),如果我们想在D::f2()中访问B1类的成员,该怎么办?有关(2),请参见问题的更新。 - FihopB2 b2; b2.test()
,它肯定是将B2
指针作为this
传递给B2::test()
,因为b2
是一个独立的对象。对于D d; d.test()
,编译器会将修复指针传递给test()
,该指针实际上指向D
的子对象B2
,因为实际调用函数是B2::test()
。如果this
在D
中没有指向B2
,那么在函数B2::test()
中访问B2
成员时就会出现问题。这就是为什么我认为我们应该将修复指针作为this
传递的原因。这个例子无法解释更新。还是要感谢。 - FihopD d; d.test()
,我同意我们可以像这样做d.test(B2* b2)
(意味着this
指向D的子对象B2)。然而,在B2:test
内部,b2->f2()
应该执行D::f2
。我是正确的吗?现在问题变成了传递给b2->f2()
的是什么类型的this
。 - Fihopvoid foo(const B2&b2){b2.f2();}
的常见情况。调用类型为D
的对象的foo()
需要起作用,但是foo()
无法传递指向类型为D
的this
指针的可能性。因此,编译器必须编译假定D :: f2()
的代码,假定隐藏的指针参数是指向B2
类型的。但是,它可以假定隐藏的指针参数指向嵌入在D
类型中的B2
类型。因此,该函数仍然可以访问D'
成员(但必须适当自动调整传入的this
指针)。 - Michael BurrB2:test
内,b2->f2()
应该执行D::f2
" 你说得对!这正是为什么在D
内传递给test()
的this
指针必须是B2
的原因,因为test()
无法调整D::f2()
的调用指针。因此,它传递了自己的this
,无论如何被调用,都可以工作,因为B2::f2
和D::f2
都期望通过this
指针传递相同的布局。 - Sergey Kalinichenko