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

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

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

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

 

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

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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 配置catalina.out的日志格式[通俗易懂]

    配置catalina.out的日志格式[通俗易懂]启动Tomcat时,catalina.out中输出的日志格式可能不太理想。看看某些版本默认的格式:四月24,20186:49:32下午org.apache.catalina.startup.Catalinastart信息:Serverstartupin9772ms有点别扭,想要调整成下面的格式:24-Apr-201818:52:16.13…

    2022年5月9日
    51
  • 去除限制 Post 请求大小限制

    去除限制 Post 请求大小限制tomcat6及以下版本 在tomcat文件夹下的conf文件中的server.xml配置中添加: maxPostSize=”0″//0表示不限制大小。tomcat7及以上版本​ 在tomcat文件夹下的conf文件中的server.xml配置中添加:​ maxPostSize=”-1″//-1表示不限制大小。​ maxPostSiz…

    2022年7月18日
    18
  • pytorch dropout用法

    pytorch dropout用法链接:https://www.zhihu.com/question/67209417/answer/302434279刚踩的坑,差点就哭出来了TT.—我明明加了一百个dropout,为什么结果一点都没变使用F.dropout(nn.functional.dropout)的时候需要设置它的training这个状态参数与模型整体的一致.比如: Cla…

    2022年6月12日
    50
  • matlab画圆函数

    matlab画圆函数function[]=circle(x,y,r)%画圆函数%circle(0,0,4);gridon%xy是中心,r是半径rectangle(‘Position’,[x-r,y-r,2*r,2*r],’Curvature’,[1,1])axisequal%为了修饰曲线的颜色,宽度,圈盘填充颜色等,可以设置其他参数等,例如%’edgecolor’,’b’,其中edgecolor表示边框颜色,后面的b是颜色参数值;%facecolor’,’r’,其中facecolor表示内部填

    2022年6月19日
    90
  • vue-响应式原理[通俗易懂]

    vue-响应式原理[通俗易懂]1.vue响应式原理核心使用的API是:Object.defineProperty(obj,key,val)会对props和data、computed中的数组和对象都进行一个遍历,这个过程其实就是赋予数据set和get方法,让数据的访问和赋值有一些内部处理2.由于vue的核心使用的是Object.defineProperty,但是IE8及其以下版本是不兼容这个API的,并且也没有提供相关的API支持这个功能,因此这也是为什么vue项目不兼容的根本原因3.在对数组和对象进行操作的过程中,会对对象进行一个

    2022年6月10日
    27
  • 单点登录

    单点登录

    2021年6月5日
    136

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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