构造函数和析构函数能不能是虚函数?
简单回答是:构造函数不能为虚函数,⽽析构函数可以且常常是虚函数。
为什么构造函数不能为虚函数?
C++对象在三个地⽅构建:(1)函数堆栈;(2)⾃由存储区,或称之为堆;(3)静态存储区。⽆论在那⾥构建,其过程都是两步:⾸先,分配⼀块内存;其次,调⽤构造函数。好,问题来了,如果构造函数是虚函数,那么就需要通过虚函数表 来调⽤,但此时⾯对⼀块 raw memeory,到哪⾥去虚函数表呢?毕竟,虚函数表是在构造函数中才初始化的啊,⽽不是在其之前。因此构造函数不能为虚函数。
为什么析构函数必须是虚函数?
因为此时 vtable 已经初始化了;况且我们通常通过基类的指针来销毁对象,如果析构函数不为虚的话,就不能正确识别对象类型,从⽽不能正确销毁对象。
原因:如果没有将基类的析构函数声明为虚函数,在释放指向派⽣类对象的基类指针的时候,只会调⽤基类的析构函数,⽽派⽣类的析构函数不会调⽤,导致属于 派⽣类新添加的数据不能释放,从⽽导致内存泄漏。构造函数可以被重载
如果将析构函数声明为虚函数,在释放指向派⽣类对象的基类指针的时候,会调⽤派⽣类的析构函数,⽽派⽣类的析构函数会⾃动调⽤基类的析构函数,从⽽使放 所有内存,避免内存泄漏。
可是这⾥会有个问题,为什么将基类析构函数声明为虚函数,在释放指向派⽣类对象的基类指针时,会调⽤派⽣类的析构函数,难道派⽣类的析构函数重写了基类的析构函数吗?函数名不同啊。
答:其实析构函数是⼀个特殊的函数,编译器在编译时,析构函数的名字同⼀命名为 destucter。
所以只要将基类的析构函数声明为虚函数即可,不管派⽣类的析构函数前⾯是否有 virtual 关键字,都构成重写,这也就可以解释为什么将基类析构函数声明为虚函数,释放指向派⽣类对象的基类 指针时,会调⽤派⽣类的析构函数,因为虚表中的函数指针指向的是派⽣类的析构函数
为什么C++默认的析构函数不是虚函数
C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占⽤额外的内存。⽽对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。因此C++默认的析构函数不是虚函数,⽽是只有当需要当作⽗类时,设置为虚函数。
C++中析构函数的作⽤
当对象结束其⽣命周期,如对象所在的函数已调⽤完毕时,系统会⾃动执⾏析构函数。
只能有⼀个析构函数,不能重载。
调⽤顺序:
构造函数:1)基类的构造函数,2)再调⽤对象成员构造函数,3)最后调⽤派⽣类的构造函数
类析构顺序:1)派⽣类本⾝的析构函数;2)对象成员析构函数;3)基类析构函数。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论