以下是代码:
#include <iostream>
using namespace std;
class T {
public:
virtual int f(int x) { cout << "T::f" << endl; return 0; }
void g() { f(1); cout << "T::g" << endl; }
virtual void h() { g(); cout << "T::h" << endl; }
};
class S: public T {
public:
int f(double y) { cout << "S::f" << endl; return 2; }
virtual void g() { f(1); cout << "S::g" << endl; }
virtual void h() { g(); cout << "S::h" << endl; }
};
int main() {
T t; S s; T * p = &s;
p -> f(1.5);
p -> g();
p -> h();
return 0;
}
我很困惑哪些函数将被执行,即使我已经阅读了几本教科书中的虚函数机制。任何帮助将受到高度赞赏。
更新:我已运行代码,输出为:
T::f
T::f
T::g
S::f
S::g
S::h
例如,我无法理解当我们已经在函数内时,我们如何选择执行哪些函数。
答案 0 :(得分:1)
在你的类中,T将默默地创建指向虚函数表的函数(你可以发现它存在,如果你将调用sizeof(T),它将在sizeof(void *)然后必须更大)。你的类S也会有另一个虚拟表的指针。
这样的虚拟表只是指向函数的指针。
当你的类S创建时,它从T创建虚拟表的副本。然后用指向S的函数的指针替换指向T定义的函数的指针。因此,它不会替换指向函数f()的指针,因为你不要在S中定义它,但它会替换指向函数h()的指针,因为你在S中重新定义了它。
因此,当第一个指针指向T :: f()并且第二个指向S :: h()时,使用虚拟表获取对象。并且您尝试使用对象T操作该对象。
所以,当你调用f()时 - 就像调用T :: f()一样。 当你调用h()时 - 就像调用S :: h()一样。
没有&#34;虚拟&#34;的方法不要输入此表。因此,T *现在将了解在子类中添加的虚方法,如果没有在对象中重新定义,T *将调用它自己的虚方法。
就是这样。