前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >构造函数调用子类的方法,写过吗?

构造函数调用子类的方法,写过吗?

作者头像
gaigai
发布2021-04-13 14:32:04
1.4K0
发布2021-04-13 14:32:04
举报
文章被收录于专栏:Windows开发Windows开发

系统学习Windows客户端开发


先看一段示例代码。

代码语言:javascript
复制
#include <iostream>
using namespace std;

class Base
{
public:
    Base() 
    {
        cout << "Base constructor" << endl;
        cout << "Value is " << GetValue() << endl;
    }

    ~Base() 
    {
        cout << "Base destructor" << endl;
        cout << "Value is " << GetValue() << endl;
    }

protected:
    virtual int GetValue() { return 1; }
};

class Derive : public Base
{
public:
    Derive() : Base() 
    {
        cout << "Derive constructor" << endl;
    }

    ~Derive()
    {
        cout << "Derive destructor" << endl;
    }

protected:
    virtual int GetValue() { return 2; }
};

int main()
{        
    Derive derive;
    return 0;
}

这段示例代码,类Derive派生于Base,Base的构造函数与虚构函数均调用虚函数GetValue(),根据C++多态特性,应该是要调用Derive的GetValue()返回2,真的是这样吗?让我们看下最终的输出。

从输出的结果看,Base的构造函数与虚构函数均调用Base的GetValue()返回1,而不是Derive的GetValue()。从汇编代码进一步确认,C++编译器确实是直接调用Base的GetValue()地址,而不是通过虚函数指针__vfptr去获得GetValue()的地址。

为什么Base的构造函数与虚构函数即使调用虚函数,也是调自己的函数呢?这跟构造函数与虚构函数的调用顺序有关。子类对象构造的时候,先调父类构造函数初始化父类,再调子类构造函数初始化子类。子类对象虚构的时候,恰恰相反,先调子类对象的虚构函数,再调父类的虚构函数。输出的结果也证明了这点。

所以如果父类的构造函数与虚构函数是调用子类的函数,那就非常危险了。因为父类的构造函数执行时,子类的构造函数还没有执行,说明子类还没有初始化,而这时就调用子类的方法,很容易出错,甚至崩溃。父类的虚构函数执行的时候,子类的虚构函数已经执行完毕,说明子类的资源已经被释放,而这时继续执行子类的方法,也很容易崩溃。于是,C++规范为此作了此约束。

如果真的很想在构造函数内调用子类方法进行初始化,还是显示提供一个初始化函数,让子类对象实例化完后,显示调用初始化函数。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Windows开发 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档