构造函数调用虚函数的问题

构造函数调用虚函数的问题

大家好,又见面了,我是全栈君。

一般情况下,不允许在构造函数或者析构函数中调用虚函数。其实语法上都没有问题,只是会失去多态性。

 

如果在构造函数中调用虚函数,会先调用父类中的实现,也就失去了多态的性质。

class A {
    public:
    virtual void print() {
        cout << "A" << endl;
    }
    A() {
        print();
    }
    ~A() {
        //print();
    }
};
class B :public A {
    void print() {
        cout << "B" << endl;
    }
};
int main() {
    A* ptr = new B;
    return 0;
}

 构造函数调用虚函数的问题

如果在析构函数中调用虚函数,也是同样的失去了多态性。

class A {
    public:
    virtual void print() {
        cout << "A" << endl;
    }
    A() {
        print();
    }
    ~A() {
        print();
    }
};
class B :public A {
    void print() {
        cout << "B" << endl;
    }
};
int main() {
    A* ptr = new B;
    delete ptr;
    return 0;
}

 

 构造函数调用虚函数的问题

 

 

 

 

出现上述结果的原因是因为,构造函数还没有将vptr和vtable初始化完毕,就调用虚函数,此时必然调用的基类中的实现。

而在析构函数中,因为子类的那部分已经被析构掉了,此时在父类的析构函数调用虚函数,调用的也只能是父类中的实现。


 

但是吧,也有的文章说如果一个类为基类的时候,必须将析构函数写为虚函数,否则子类那部分无法释放。

https://blog.csdn.net/starlee/article/details/619827 

我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明:    
    有下面的两个类:

class ClxBase
{

public:
    ClxBase() {};
    virtual ~ClxBase() {};

    virtual void DoSomething() { cout << “Do something in class ClxBase!” << endl; };
};

class ClxDerived : public ClxBase
{

public:
    ClxDerived() {};
    ~ClxDerived() { cout << “Output from the destructor of class ClxDerived!” << endl; }; 

    void DoSomething() { cout << “Do something in class ClxDerived!” << endl; };
};
    代码

ClxBase *pTest = new ClxDerived;
pTest->DoSomething();
delete pTest;
    的输出结果是:

Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
    这个很简单,非常好理解。
    但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:

Do something in class ClxDerived!
    也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
    所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
    当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。

转载于:https://www.cnblogs.com/LUO77/p/5907297.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/108862.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • TaskScheduler_taskset -p

    TaskScheduler_taskset -p目录1、DAGScheduler与TaskScheduler2、TaskScheduler与SchedulerBackend3、任务调度过程总结1、DAGScheduler与TaskSchedulerDAGScheduler面向我们整个Job划分出了Stage,划分了Stage是从后往前划分的,执行的时候是从前往后,每个Stage内部有一系列任务,Stage里面的任务是并…

    2022年10月11日
  • 使用 UpdatePanel

    使用 UpdatePanel1概述ASP.NETUpdatePanel控件能让你创建丰富的、以客户为中心的Web应用程序。使用UpdatePanel控件,可以刷新选择的页面部分而不是使用回发来刷新整个页面,这就像是执行了一个局部页面更新一样。包含一个ScriptManager和一个或多个UpdatePanel的Web页面会自动加入局部页面更新,而不需要定制客户端代码。1.1场景…

  • Kubernetes技术架构分享(Springboot on k8s代码演示)

    Kubernetes技术架构分享(Springboot on k8s代码演示)

  • 暑假训练赛第六场

    暑假训练赛第六场

  • 毕业设计 – 题目:基于stm32的智能扫地机器人设计与实现

    1课题背景随着人口老龄化的到来和人民对提升生活品质的需要,人们对在现实生活场景中取代人力的服务机器人有着迫切的需要。同时,机电、自动控制、计算机、传感器等技术的发展也为制造服务机器人提供了技术支持。扫地机器人是服务机器人中技术最成熟和最为广泛使用的机器人。它可以自动的在室内行走,通过刷扫和吸尘将地面上的碎屑吸收进垃圾收集装置中,完成清洁地面的任务,有效的减少了人们清洁地面这种简单重复的家务劳动,节约了劳动力,提高了生活品质。对于许多忙于工作和生的人来说,扫地机器人已经成为家庭必

  • 谈谈怎么实现Oracle数据库分区表「建议收藏」

    谈谈怎么实现Oracle数据库分区表「建议收藏」Oracle数据库分区是作为Oracle数据库性能优化的一种重要的手段和方法,做手头的项目以前,只聆听过分区的大名,感觉特神秘,看见某某高手在讨论会上夸夸其谈时,真是骂自己学艺不精,最近作GPS方面的项目,处理的数据量达到了几十GB,为了满足系统的实时性要求,必须提高数据的查询效率,这样就必须通过分区,以解燃眉之急!先说说分区的好处吧!1) 增强可用性:如果表的某个分区出现故障,表在其他分

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号