关于构造函数、析构函数,高手进,求分析。。。。。

brk1985 2010-11-16 12:53:40



#include <iostream>

struct Base {
Base() {}
virtual ~Base()
{
std::cout << "Base destroyed" << std::endl;
}
};

struct Derived : Base {
~Derived() {
std::cout << "Derived destroyed" << std::endl;
}
};

int main() {
Base *b = new Derived();delete b;//输出结果:Derived destroyed、Base destroyed;
//const Base &b1 = Derived();//基类析构函数不设为虚函数,输出结果:Derived destroyed、Base destroyed、Derived destroyed、Base destroyed;
//const Base &b1 = Derived();//基类析构函数设为虚函数,输出结果:Derived destroyed、Base destroyed;
//Derived();//输出结果:Derived destroyed、Base destroyed,为什么会调用基类析构函数?
//Base b2 = Derived();//输出结果:Derived destroyed、Base destroyed、Base destroyed;
return 0;
}



1. Base *b = new Derived();delete b;没有什么问题,最基本的,好理解;
2. const Base &b1 = Derived();基类的析构函数virtual去掉,输出4条语句?很意外,为什么不是两条?还有不解的是为什么构造函数可以作为右值赋值给类对象(构造函数不是没有返回类型吗?)?
3. const Base &b1 = Derived();基类的析构函数virtual加上,输出2条语句,不知道与2区别在哪里?
4. Derived();为什么会调用基类析构函数?
5. Base b2 = Derived();为什么输出3条语句?
...全文
286 30 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
brk1985 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 jikeyuan1 的回复:]

在继承层次中析构函数一定要定义为虚函数 ,运行时多态,不然Base *b;b= new Derived();这条语句只会调用基类的析构函数,而造成内存的泄露,因为你b是基类指针,没有virtual的话,基类指针是只能见到自己类中的函数,对于派生类中的成员是见不到的,所以不可能调用子类的析构函数,还有LZ说什么会出现四条结果,那是不可能的 LZ的编译器可以换掉啦
[/Quote]

原程序有这么一段的。。。就上面程序都是2条,这个又牵涉到宏定义了。。。呵呵,结贴。。。
#if defined CONSTRUCTOR_DEFINED
Base() {}
#endif
jikeyuan1 2010-11-16
  • 打赏
  • 举报
回复
在继承层次中析构函数一定要定义为虚函数 ,运行时多态,不然Base *b;b= new Derived();这条语句只会调用基类的析构函数,而造成内存的泄露,因为你b是基类指针,没有virtual的话,基类指针是只能见到自己类中的函数,对于派生类中的成员是见不到的,所以不可能调用子类的析构函数,还有LZ说什么会出现四条结果,那是不可能的 LZ的编译器可以换掉啦
龙哥依旧 2010-11-16
  • 打赏
  • 举报
回复
把这帖子结了吧
把没懂的地方再发个新帖!
job82824 2010-11-16
  • 打赏
  • 举报
回复
你要是用过MFC就会发现,里面所有自定义的类和派生类的析构函数都自动会在前面添加上virtual声明的。就算你去掉这个,编译器也是添加了的。就在tooltips里面有显示的。

所以 呵呵...
brk1985 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 qq120848369 的回复:]

谁会用const Base& a=Derived();
[/Quote]

变态试题吧。。。
这语句意思是:把派生类临时对象转换成基类对象,并被a引用?不知道我有没有理解错误?
qq120848369 2010-11-16
  • 打赏
  • 举报
回复
谁会用const Base& a=Derived();
brk1985 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 brk1985 的回复:]

引用 2 楼 ddlddy 的回复:

2.你的virtual不加的话Base *b = new Derived();delete b;基类不会析构const Base &amp;b1 = Derived();这个没影响,“=”是类的赋值函数,如果没有定义会有默认的,属于操作符重载。
3.没有区别Base *b = new Derived();delete b;这个时候能看出来区别……
[/Quote]

22楼纠正下,得出的结论是在基类指针指向派生类对象的时候,加virtual语句起到的作用是调用派生类析构函数。。。
brk1985 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ddlddy 的回复:]

引用 1 楼 gules 的回复:
Derived()将产生一个派生类的临时对象,且派生类析构函数会自动调用其基类的析构函数。

派生类析构函数会自动调用其基类的析构函数?
[/Quote]

发现确实这样,第4点疑问解决。。。
brk1985 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 ddlddy 的回复:]

2.你的virtual不加的话Base *b = new Derived();delete b;基类不会析构const Base &b1 = Derived();这个没影响,“=”是类的赋值函数,如果没有定义会有默认的,属于操作符重载。
3.没有区别Base *b = new Derived();delete b;这个时候能看出来区别
4.自动调用的。
5.有临时对象。
[/Quote]

我的意思是第二点(不加virtual)与第三点(加virtual)疑问区别在哪里?为什么加了virtual,输出4条语句,不加才输出2条,我不明白为什么?

加virtual的作用,很明显,Base *b = new Derived();delete b;这2条语句也调用了派生类的析构函数,否则只调用基类的析构函数,所以出问题。。。得出的结论是在基类指针指向派生类对象的时候,加virtual语句起到的作用是调用派生类对象。。。

但是为什么const Base &b1 = Derived();这条语句,加与不加virtual,也会不同?一般书里提到虚析构函数,只谈到上面这点结论,没提到引用这种情况。。。
龙哥依旧 2010-11-16
  • 打赏
  • 举报
回复
brk1985
可以结贴了!
liutengfeigo 2010-11-16
  • 打赏
  • 举报
回复
Base b2 = Derived();
这算不算是子类的对象转化父类对象呢?
一个临时D用它的一部份B去复制构造b2而已
gules 2010-11-16
  • 打赏
  • 举报
回复
当子类的对象转化父类对象时,会发生“切割”(除非是对象的引用或指针),什么虚不虚的都没用!
龙哥依旧 2010-11-16
  • 打赏
  • 举报
回复
引用百度的搜索
当子类的对象转化父类对象时,如果析构函数不是虚函数,则会执行父类的析构函数。则可能造成该对象(主要是子类对象特有的资源)不能被释放,造成资源泄漏。
那么
Base b2 = Derived();
这算不算是子类的对象转化父类对象呢?
liutengfeigo 2010-11-16
  • 打赏
  • 举报
回复
难道楼主还不知道复制构造函数和赋值操作符在这里是很麻烦的?
龙哥依旧 2010-11-16
  • 打赏
  • 举报
回复
gules 2010-11-16
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 ddlddy 的回复:]
猜想一下,如果没加Base::~Base();派生类调用基类的析构,那么添加后,会重复调用吗?
[/Quote]

别猜了,自己试试吧!(提示:注意编译器)
龙哥依旧 2010-11-16
  • 打赏
  • 举报
回复
猜想一下,如果没加Base::~Base();派生类调用基类的析构,那么添加后,会重复调用吗?
liutengfeigo 2010-11-16
  • 打赏
  • 举报
回复
一切都是对的。
只是你没理解好而已。
gules 2010-11-16
  • 打赏
  • 举报
回复
自己运行看看就知道了。
liutengfeigo 2010-11-16
  • 打赏
  • 举报
回复
因为有了virtual
加载更多回复(9)

65,187

社区成员

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

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