免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1394 | 回复: 5
打印 上一主题 下一主题

[C++] 【求助C++问题】有关虚拟析构函数的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-02-16 21:48 |只看该作者 |倒序浏览
一个特简单的程序,增加基类的虚拟析构函数,则程序输出不一致。请哪位懂C++解释一下其中的道道?

#include <iostream>
#include <string>
using namespace std;
class base
{
        public:
                virtual void print(){cout<<"base::print()"<<endl;}
                //virtual ~base(){}//增加虚析构函数,将导致输出不一致。
};
class derived :public base
{
        public:
                virtual void print(){cout<<"devrived::print()"<<endl;}
};
int main(int argc, char *argv[])
{
        base* p1=&derived();
        p1->print();

        derived d;
        base* p2=&d;
        p2->print();

        return 0;
}


加入虚拟析构函数后,输出为:
base::print()
devrived::print()
不加入虚拟析构函数,输出则为:
devrived::print()
devrived::print()

[ 本帖最后由 运动补偿 于 2006-2-16 22:57 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2006-02-16 21:54 |只看该作者
base* p1=&derived();
有这样的语法,不会报错?

什么不同?

论坛徽章:
0
3 [报告]
发表于 2006-02-16 23:17 |只看该作者
谈谈我的看法,不一定对,大家指教~~

实际上,第一个赋值指向的是一个临时对象,加入与没有加入虚拟析构函数的区别在于:加入之后,在derived类中会合成一个析构函数以便调用base的虚拟析构函数,如果没有加入的话那么就不会合成这个析构函数,所有的资源在main函数结束之后才回收.

因此,对于代码: base* p1=&derived();
没有加入虚拟析构函数的时候因为derived()函数生成的临时对象没有被销毁,因此对它的调用是对derived的调用;当加入虚拟析构函数之后,derived()函数生成的临时对象在以上的赋值完成之后就会调用析构函数进行析构,这个时候再次对p1调用print函数时,因为临时对象已经析构,那么这个调用就是对base的调用了.

我做了一个实验的代码,加了一些东西,大家看看~~

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. class base
  5. {
  6.         public:
  7.                 virtual void print(){cout<<"base::print()"<<endl;}
  8.                 virtual ~base(){cout << "~base()\n";}//增加虚析构函数,将导致输出不一致。
  9. };
  10. class derived :public base
  11. {
  12.         public:
  13.                 virtual void print(){cout<<"devrived::print()"<<endl;}
  14.                 //virtual ~derived(){cout << "~derived()\n";}//增加虚析构函数,将导致输出不一致。
  15. };

  16. int main(int argc, char *argv[])
  17. {
  18.         derived *t = &derived();
  19.         base* p1 = t;
  20.         p1->print();

  21.         derived d;
  22.         base* p2=&d;
  23.         p2->print();

  24.         // 第一部分相当于以下的代码
  25.         // 用temp模拟临时对象
  26.         derived temp;
  27.         derived *s = &temp;
  28.         base *p3 = s;
  29.         // 这次调用是对derived的函数调用
  30.         p3->print();
  31.         // 显式地对temp进行析构
  32.         temp.base::~base();
  33.         // 析构完后,同样的一个内存,却是用base指针去解释,
  34.         // 因此调用的是base的函数
  35.         p3->print();

  36.         return 0;
  37. }
复制代码

论坛徽章:
0
4 [报告]
发表于 2006-02-17 13:27 |只看该作者
楼上的大哥,您的大意我是明白了.
但是有一个细节我不明白:
"当加入虚拟析构函数之后,derived()函数生成的临时对象在以上的赋值完成之后就会调用析构函数进行析构,这个时候再次对p1调用print函数时,因为临时对象已经析构,那么这个调用就是对base的调用了."
我的疑问是:
p1所指的对象被析构的时候,析构函数对此对象做了什么导致------析构后还能够用p1调用基类的成员函数.?

刚开始学c++ .多指教.
3x

论坛徽章:
0
5 [报告]
发表于 2006-02-17 13:55 |只看该作者

回nuclearweapon

这个问题就好像用不同的指针去解释同一块内存,会有不同的结果一样的道理,你先想想看,我回头再仔细说~~

论坛徽章:
0
6 [报告]
发表于 2006-02-17 14:14 |只看该作者
我是这样想的:

通过一个 _对象指针_ 访问 _虚函数_ , 要根据 _对象指针_  所指的对象类型来动态的决定调用哪一个函数.
既然一个 _对象指针_  所指的 _对象_ 已经不存在了,为什么还可以调用对象的成员函数.?
而且调用对象的成员函数是基类的成员函数?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP