关于virtual的析构函数

tiancaiak 2007-01-06 03:28:01

加virtual是为了继承来多态的

不是说析构函数不能被继承吗?
...全文
1527 35 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
junfeng_feng 2011-01-18
  • 打赏
  • 举报
回复
大四了,毕业了,找工作时,这个问题问的很多。可是我却不回
shenmea00000 2007-01-08
  • 打赏
  • 举报
回复
概念没有搞清楚
继承是继承,多态是多态
leaber 2007-01-08
  • 打赏
  • 举报
回复
呵呵,DELPHI里面的析构一直是这么干的。
Enigmaya 2007-01-08
  • 打赏
  • 举报
回复
析构函数本来就没有继承,子类都有自己的析构函数。
用virtual是override的问题,一般在父类中使用virtual函数,子类会再去实现同样名称的函数,如果是继承,用的着去自己再去实现么?所以很明显这不是为了继承。


所以搂住的概念错了:virtual != 继承
rabbitweng 2007-01-08
  • 打赏
  • 举报
回复
为了构造和析构配对,如果没有virtual的话,一旦出现继承,就会出现构造(子类的构造函数)和析构(父类的析构)进行配对,这是不应该出现的
taodm 2007-01-08
  • 打赏
  • 举报
回复
楼主,析构函数是不能被继承,但是编译器会自动生成析构函数(具体条件看effective c++),这个自动生产的析构函数会调用基类的析构函数。
tiancaiak 2007-01-08
  • 打赏
  • 举报
回复
不好意思,新手,写的代码确实很少,又不聪明,所以问题总是so多,还请多多包涵*~_~*
谢谢大家!
caitian6 2007-01-07
  • 打赏
  • 举报
回复
mark
foreverlearning 2007-01-07
  • 打赏
  • 举报
回复
当基类的指针需要调用其派生类对象时,需要将基类的虚构函数声明为virtual,析构的时候才能将基类和派生类的对象析构掉
axx1611 2007-01-07
  • 打赏
  • 举报
回复
问这种问题一看就知道程序写得太少了
很多东西在你写程序时自然会遇到 那个时候你的理解才是最深刻的!!
tiancaiak 2007-01-07
  • 打赏
  • 举报
回复
非常感谢大家!我从中受益匪浅!

关于"析构函数前加virtual"这个问题,综合大家的指点和书上的话,我想如果我理解的没有什么错误的话,它是这样子的:

//////////////////////////////////////////////////////////////////////////////////
首先,每个派生类对象都有一个指向虚函数表的指针,访问任何虚函数都是间接通过这个指针进行的,之所以要用虚函数表,是因为调用一个虚函数的哪个版本是在运行过程(调用时指针所指的对象)才能确定的(动态绑定)。
相对于虚函数,实函数的调用机制就简单的多:由于每个实函数只有一个版本,因此调用地址在编译时即可确定(静态绑定)

析构函数也可以通过virtual修饰而声名为虚函数,虚析构函数与一般虚函数的不同之处在于:
1》它的重定义函数就是派生类的析构函数,但不要求同名。
2》一个虚析构函数的版本被调用后,接着就要调用执行基类版本,依次类推,直到调用执行了派生序列的最开始的那个虚析构函数版本为止。

//////////////////////////////////////////////////////////////////////////////////
以上引自《全国计算机等级考试二级教程——C++语言程序设计》

也就是说,Base *p=new Derive; 产生的对象是Base的.

当不在基类前不加virtual时,派生类的析构函数不加入虚函数表中,此时析构函数就是实函数,只有一个版本,就是对象自己的~Base();

当基类前加virtual时,派生类和基类的析构函数都加入虚函数表中,调用析构函数的时候就调用当前指针所指的那个版本的析构函数.之后的事情:一个虚析构函数的版本被调用后,接着就要调用执行基类版本,依次类推,直到调用执行了派生序列的最开始的那个虚析构函数版本为止。

5555~ 真是不容易啊~
我想说一句——理解万岁!!太谢谢大家了!!!

最后,在结贴前再麻烦大家帮忙看看上面写的有什么不对的地方^-^
IMGGTOO 2007-01-07
  • 打赏
  • 举报
回复
这样难得的好帖子,得顶!
zhhonghui 2007-01-07
  • 打赏
  • 举报
回复
请楼主参考Effective C++,
看下面的情况:
base *b = new derive();
delete b;
这段代码应该是合法的,编译也能够得到通过,但是行为却不是我们所预期的,
我们期望delete删除derive对象占用的全部资源,但是,如果我们没有给~base()函数加
virtual的话delete的实际行为只是释放了对象的base部分,而对象的derive特有部分将
不被释放,成为资源泄露的隐患。
加上virtual就是提示delete调用derive版的析构函数。
a_b_c_abc8 2007-01-06
  • 打赏
  • 举报
回复
当一个基类指针实际指向派生类
==>
当一个基类指针实际指向派生类的对象
a_b_c_abc8 2007-01-06
  • 打赏
  • 举报
回复
1>>>>我上面理解的对不对?
2>>>>为什么 若没有virtual,delete p;就少调用一个析构函数?
3>>>>为什么若有virtual,delete p;就调用两个析构函数?
==============
一个派生类的析构函数最后是会自动调用基类的析构函数的.这就象派生类构造函数在一定条件下会自动调用基类的无参构造函数一样.
如果一个基类析构函数置为virtual,那么派生类并不是说会继承基类的析构函数,而是会继承"虚"的机制,派生类析构也会置为virtual. 此时,当一个基类指针实际指向派生类,在delete的时候,发生的是动态绑定,正确调用到派生类的析构函数,但派生类的析构函数只会析构派生类新增加的部分,从基类继承的部分,要靠基类的析构函数来析构,而基类的析构函数是由派生类析构函数执行完毕时自动调用的.
相反,如果基类析构函数不为虚,派生类析构函数也就不为虚.当一个基类指针实际指向派生类,在delete的时候,发生的是静态绑定,编译器根据指针的类型直接绑定到基类析构函数,自然派生类的析构函数就不会被调用.

并不是所有用于继承的类的析构函数都要置为virtual,只有 有多态目的的基类的析构函数才置为virtual.
lin_style 2007-01-06
  • 打赏
  • 举报
回复

casale(无三) ( ) 信誉:100 Blog 如果析构函数不用virtual,则
Base *p = new Derive();
delete p;
这里delete p删除的就是Derive类中的Base成份了,而对于Derive成员则无法删除,所以为了正确删除,则必须用virtual析构函数,具体请参考effective c++ 3td

//无三先生这段讲得很明白了。两个不是一个概念
  • 打赏
  • 举报
回复
2>>>>为什么 若没有virtual,delete p;就少调用一个析构函数?
3>>>>为什么若有virtual,delete p;就调用两个析构函数?

如果基类的析构不是virtual, 那么Base *p; p = new Derive; delete p;这个时候就调用基类的析构。而如果基类是virtual,那么delete p 这个操作就执行多态,执行子类的析构。你只需要理解虚函数的行为就可以了。也许你写多了代码就自然明白了吧。
axx1611 2007-01-06
  • 打赏
  • 举报
回复
当然对于执行效率要求很高的程序除外~~
带虚函数就会有虚表,就牵扯到动态联编,对效率会有一些影响,不过应用程序更多的还是结构比较重要。。。
axx1611 2007-01-06
  • 打赏
  • 举报
回复
如果不是密封类就最好把析构函数都写成虚的,这是一个好习惯,可以避免很多问题
cutenoob 2007-01-06
  • 打赏
  • 举报
回复
4:当类中有一个或多个virtual函数时,就应当把它的析构函数定义为virtual
-------
如果一个类中virtual函数的话,创建者就很明确的告诉你 这个类是用来继承的 很明显 析构当然要virtual了


lz也别灰心,,能有自己的看法才能看进去
加载更多回复(15)

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧