子类构造函数中调用虚函数问题验证

 一、问题探讨

  大家是否有在子类或基类构造函数中调用虚函数的情况呢?语法是否支持?执行情况如何呢?为什么呢?

二、问题验证

  这个问题的最好答案是亲自写个demo调试下看看结果如何,下面是demo代码(vs2019):

 1 class Base {
 2 public:
 3     Base() {
 4         cout << "Base::ctor\n";
 5         Func();
 6     }
 7     virtual void Func() {
 8         cout << "Base::Func\n";
 9     }
10 };
11 
12 class D : public Base {
13 public:
14     D() {
15         cout << "D::ctor\n";
16         Func();
17     }
18 
19     void Func() override {
20         cout << "D::Func\n";
21     }
22 };

  客户端调用代码

1 int main()
2 {
3     auto d = std::make_shared<D>();
4 
5     return 0;
6 }

  输出结构如下:

      

   子类构造函数调用虚函数调用的是子类重写的,基类构造函数调用的是基类的虚函数。可以回答问题中的前两个疑问,语法支持,执行情况如上;但是并没有调用子类重新的虚函数呢?继续分析。

三、原因分析

  回答这个问题,我们可以直接使用VS2019的调试器即可。我们需要在基类和子类的构造函数中分别打上断点,如下:

    

   我们知道构造子类前需要先构造基类,在进入基类构造函数实现体前,虚函数表是空的:

   

  进入构造体后,虚表指向基类的虚函数地址:

   

   进入子类构造体前,虚表还是基类的虚函数地址:

   

   进入子类构造体后,虚表地址替换为子类的:

   

  通过上面详细的调试步骤和对象内存虚表信息即可知道为什么了吧!

posted @ 2021-03-26 22:07  blackstar666  阅读(262)  评论(0编辑  收藏  举报