为什么一个类里可以有几个构造函数而只能有一个析构函数?

writing0 2003-12-29 08:05:33
为什么一个类里可以有几个构造函数而只能有一个析构函数?
...全文
2668 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
hpho 2003-12-31
  • 打赏
  • 举报
回复
为什么要多个析构?
唔~` 我想一个构造对应一个析构.

所以我想仍然有需要多个析构的时候.
事实上多个析构就是继承虚析构.(基类里的是virtual destructor)
所谓多个就是为了有选择性的调用.

所以我认为有这种需求, 但它的表现并不像构造函数那样, 它"多个"表现的方式是继承.
glacierrr 2003-12-31
  • 打赏
  • 举报
回复
好像看候捷先生的书时看到过这个问题的解答,找找看
dongdong715 2003-12-30
  • 打赏
  • 举报
回复 1
呵呵,,有析构函数重栽吗?
abitz 2003-12-30
  • 打赏
  • 举报
回复
1。 flyinger(风往北吹) 的这个程序:
class fly
{
public:
fly(){}
void test() {cout<<"The object exists!";}
~fly(){}
};
int main()
{
fly flyinger;
flyinger.~fly();//那么这个对象时候还存在呢!
flyinger.test();
//如果编译通过的话,运行的结果可以告诉你一点什么东西呢!
}

vs.net2003编译正常通过,结果为:
The object exists!

没看出来flyinger(风往北吹) 想说的是什么意思;这里我只能讲一下自己的看法:
总的看来,这个程序没有编译通不过的理由:dtor只会摧毁对象,不会释放内存。
而flyinger.test();这句会被展开为普通函数调用test(&flyinger)的形式(test非虚),
此时&flyinger会得到合法的地址,因此test(&flyinger)是合法的。这也可以看出,
利用test这种形式是不能判断一个object是否存在的。

2。前面_goolooloo_(_goolooloo_) 说fly的这个dtor什么也不干,是对的,
这符合当前fly的情况。但是,如果fly中有具有non-trivival dtor的data member,
那么这个dtor是会去调用这些data member的dtor的。
关于这点,这里有几个例子:
《1》如果加入一个data member,其具有trivival dtor,那么在析构前后,对object不会
有影响,也就是说,dtor什么也不作。
《2》如果加入一个data member,其具有non-trivival dtor,那么在析构之后,
该data member也会被析构。
《3》如果加入一个virtual function,使object model中含有vptr,那么在析构之后,
该vptr依然有效。个人怀疑是由于可将vptr视为一data member,由于其具有trivival dtor
(vptr为一指针类型),所以fly的dtor不会对它有什么作为。
关于这些,大家可以很容易的写出例子。

3。关于dtor只会摧毁对象,不会释放内存。
前面好像有人认为dtor会释放内存,这是不对的。dtor不会释放内存。
前面这个例子:
int main()
{
fly flyinger;
flyinger.~fly();
flyinger.test();
}
从道理上讲,是不安全的,因为fly的dtor会被调用两次。而对一个object调用两次
dtor,其结果未有定义。(但这里由于fly的dtor其实是trivival的,故无大碍)
因此,我前面写的例子中,是用placement new在object原有的内存上又构造了一个object,来防止对同一个object调用两次dtor的:
void main()
{
aaa b;
b.~aaa(); //这里是有机会写b.~aaa(1, 2);的
new(&b) aaa;
}
尽管这样不是异常安全的(详见exceptional C++),但示意用足已。

总之,关于这个问题,说由于dtor只能被间接由delete或系统调用,因此不能重载,
似乎是说不过去的。个人以为dtor之所以不能被重载,一是由于dtor的工作比较单一,没有
重载的必要,二是由于delete提供了调用dtor的保证,但却没有提供调用不同版本dtor的
语法,导致如果重载dtor,会使调用不明确。其他的原因我暂时还没想到,还望高人指点。
abitz 2003-12-30
  • 打赏
  • 举报
回复
我不明白为什么要显示自己去调用析构函数,一个实体析构两次或多次,有必要吗?
============================================================================
显式调用dtor不是为了将一个实体析构两次或多次,而是就地摧毁对象。
这样可以把对象的摧毁与内存的释放分开,它和把内存的分配与对象的构造
分开是对应的。至于用处,建议您看一下关于对小对象进行内存分配的方面的应用,
比如sgi STL的allocator
cxjddd 2003-12-30
  • 打赏
  • 举报
回复
析构函数应该有足够的信息来完整地释放资源。

而构造函数需要参数来获得足够的信息来生成一个对象。
FredWorks 2003-12-30
  • 打赏
  • 举报
回复
构造函数可以有很多个,
相当于重载一样,
每一个都有自己的特点,
但是只可以选择一个来使用。
析构函数只需要完成是释放,
不想构造函数有很多不同的工作要做,
所以析构函数只有一个。
而且,析构函数只能由系统调用,
而构造函数可以由程序员自己调用。
freelong2003 2003-12-30
  • 打赏
  • 举报
回复
我非常同意ntxs(唉!一个人好难)的看法!!

不同的构造函数可以构造出不同的对象,而析构函数只需要完成相同的功能,就是释放清空。所以根本没有必要有多个析构函数。(这是站在功能的角度上说的)

而站在用户的角度看,我们无需再为对象析构时应该调用哪个析构函数而烦恼了。:)
loveghb 2003-12-30
  • 打赏
  • 举报
回复
大家为什么都想这么复杂
因为构造可以根据参数来,有不同的情况。但是析构一般都一种,所以系统默认就调用拉。
我不明白为什么要显示自己去调用析构函数,一个实体析构两次或多次,有必要吗?
如果你一个对象要分不同的方法析构的话,那你自己写一些函数好了,为什么就一定要用C++规定的析构函数呢?
DELPHI好象就可以有好多析构函数。
我正在学习DELPHI中,好象它的构造和析构都要自己来的。(错了也别怪我!)

baghatur 2003-12-30
  • 打赏
  • 举报
回复
从编译器的角度看,多个构造函数可以通过overload来确认具体调用哪个构造函数。而析构函数呢?析构函数不能有参数,所以你根本无法写出多个析构函数而又能被编译器正确理解。
_goolooloo_ 2003-12-30
  • 打赏
  • 举报
回复
在VC的DEBUG模式下,通过查看反汇编代码,可以看到,直接调用析构函数的语句完全没有任何作用.就和没有这一句一模一样.由此看来,析构函数式自动调用的,如果重载了,就会找不出正确的析构函数。


……
14: a->bbb = 345;
0040105B mov ecx,dword ptr [ebp-4]
0040105E mov dword ptr [ecx],159h
15: a->~A();
16: a->fun();
00401064 mov ecx,dword ptr [ebp-4]
00401067 call @ILT+15(A::fun) (00401014)
……
laomai 2003-12-30
  • 打赏
  • 举报
回复
mark
spirix 2003-12-30
  • 打赏
  • 举报
回复
现在给你一块橡皮泥,让你捏成一个人,那么你有多种捏法[多个构造方法],可以捏成欧洲人,亚洲人,白人,黑人,男人,女人...,当你捏好了,让你把你捏好的东西扔掉,你只有一个固定的东西可以扔[一个析构方法],就是你捏好的人!
ipgk 2003-12-30
  • 打赏
  • 举报
回复
析构函数:程序可以直接调用,不能重载。
至于为什么只能有一个,在于它的地位,因为析构函数不作对于外界的接口,所以它不需要参数也没有返回值。
构造函数负责对象的构造,公有函数负责与外界的接口,析构函数负责对象的销毁,对象各个部分都是分工明确的,更有利于对象的使用。
langzi8818 2003-12-29
  • 打赏
  • 举报
回复
不知道。规则可能就是这样的吧,没有那么多为什么
Robin 2003-12-29
  • 打赏
  • 举报
回复
也许编译通不过,因为编译器会自动的添加对象的destructor,会destruct一个已经不存在的对象,就会出错!
Robin 2003-12-29
  • 打赏
  • 举报
回复
就是说我们直接调用了Destructor的结果是什么,对象时候存在呢!
Robin 2003-12-29
  • 打赏
  • 举报
回复
这个问题很好!
不信你这么试:
显式的调用了Destrucor之后会出现什么?
class fly
{
fly();
void test() {cout<<"The object exists!"};
~fly();
}
int main()
{
fly flyinger;
flyinger.~fly();//那么这个对象时候还存在呢!
flyinger.test();
//如果编译通过的话,运行的结果可以告诉你一点什么东西呢!
}
abitz 2003-12-29
  • 打赏
  • 举报
回复
而且你只能通过delete间接调用析构函数,或者用系统调用(在对象生存期结束时),你又怎么为他传递参数呢。
========================================
传递参数是有可能的。
看这个:
struct aaa
{
aaa(){}
~aaa(){cout << "dtor called" << endl;}
};

void main()
{
aaa b;
b.~aaa(); //这里是有机会写b.~aaa(1, 2);的
new(&b) aaa;
}
结果为:
dtor called
dtor called

但是由于delete并不具有跟new等价的语法,使得在delete时无法传递参数,
而delete又肩负调用dtor的责任,则如果存在多个dtor,会使调用不明确。
cai114 2003-12-29
  • 打赏
  • 举报
回复
析构函数一个就够用了
它是用来delete的
我太菜还没想用它来执行别的功能,
加载更多回复(6)

65,180

社区成员

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

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