我的问题是参考这个问题,它解释了虚拟函数在对象切片的情况下如何工作,最终调用基类虚拟函数。 维基百科文章解释了以下代码的派生类的虚拟表布局:
class A {
public:
virtual void func() { cout << "\n In A:func"; }
};
class B: public A {
public:
virtual void func() { cout << "\n In B:func"; }
};
main() {
A *ptr1 = new B();
A oA = *ptr1;
oA.func();
}
DerivedClassObjectB:
+0: pointer to virtual method table of B
virtual method table of B:
+0: B::func
上面的程序输出“In A::func”。但是,如果没有类
B
的虚拟表了解基类 A::func
,最终会调用 A::func
吗?
A oA = *ptr1;
这会将所有成员变量复制到新的 A 对象中。 vtable 指针不是普通的成员变量,并且“不”被复制。因此,针对该对象调用的任何后续虚函数都将表现为它是 A 对象,因为它是 A 对象。
B
”?类
B
的虚拟表根本不参与 oA.func()
调用。对象 oA
具有类型 A
,这意味着它的虚拟表是类 A
的虚拟表。此外,大多数编译器都会优化
oA.func()
调用,使其根本不会使用任何虚拟表。由于
oA
的类型在编译时已知,因此 oA.func()
调用可以立即定向到 A::func
,而无需使用任何虚拟表。