为什么虚析构函数名不一样
⑴ 为什么基类与派生类的析构函数不一样,却可以实现多态
无关其它,要非这样说,只能归结于c++机制. 虚函数要求函数名一样,其实现多态的本质是:
父类* =new 子类,但如此一来,指针就变成父类的了,delete 指针的时候,由于c++会指针类型来调用析构函数,这样就调不到子类析构,有一解决办法是把该父类指针转成new时的子类指针,这样就会调到子类析构,但很多情况下父类根本就不知道是否有子类,就不能盲目强转,为了解决这一矛盾,就加了析构可以是虚函数,一般用在父类有virtual成员时,其析构必为virtual。
LZ想问的是虚函数要求名字一样,而析构名字根本就不一样怎么可能是虚函数,因为析构是和类名一样的,如果析构名字一样就会出现类重定义了,它是析构名字和虚函数双方妥协而要同时满足多态机制的产物,当然,单从虚函数的角度来看它肯定是不满足的。
⑵ 关于虚拟析构函数的问题
书不能读死,这本书看不懂,另找一本对照一下。
随便在网上找了个参考的:
构造函数不能用虚拟,因为用也没用,不管是在栈上构造对象,还是在堆上构造对象,也不管你以后是否使用父类的指针或引用来指向或引用这个对象,在构造的那“一瞬间”,总归要指明要构造对象的具体类型,所以,对象在构造过程中不存在运行时动态绑定的多态行为。
你理解这个意思吗?举了例子就明白了,通常,假如A是B的父类,
A* p = new B();
则对于虚拟函数f,可以通过A类的指针p直接调用到B类的函数,这就是运行时的多态:
p->f();
但你注意没有,B类的对象却必须通过“A* p = new B();”来构造,显然不能通过“A* p = new A();”来构造一个B类对象——这是荒唐的,这只能构造一个A类的对象。所以构造函数虚拟无意义。
但析构函数就不同了,p明明是个A类的指针,如果析构函数不是虚拟的,那么,你后面就必须这样才能安全的删除这个指针:
delete (B*)p;
但如果构造函数是虚拟的,就可以在运行时动态绑定到B类的析构函数,直接:
delete p;
就可以了。这就是虚析构函数的作用。而事实上,在运行时,你并不是总是能知道p所指对象的实际类型从而进行强制转换,所以,C++语言既然要支持多态,也就必须支持虚拟析构。
⑶ 虚析构函数的介绍
虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。如果某个类不包含虚函数,那一般是表示它将不作为一个基类来使用。当一个类不准备作为基类使用时,使析构函数为虚一般是个坏主意。因为它会为类增加一个虚函数表,使得对象的体积翻倍,还有可能降低其可移植性。所以基本的一条是:无故的声明虚析构函数和永远不去声明一样是错误的。实际上,很多人这样总结:当且仅当类里包含至少一个虚函数的时候才去声明虚析构函数。抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单:在想要成为抽象类的类里声明一个纯虚析构函数。
⑷ 为什么构造函数不能声明为虚函数,析构函数可以
构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。 不建议在构造函数和析构函数里面调用虚函数。构造函数不能声明为虚函数的原因是:1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。析构函数设为虚函数的作用: 解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。 例: #include "stdafx.h" #include "stdio.h"class A{public:A();virtual~A();};A::A(){}A::~A(){printf("Delete class APn");}class B : public A{public:B();~B();};B::B(){ }B::~B(){printf("Delete class BPn");}int main(int argc, char* argv[]){A *b=new B;delete b;return 0;} 输出结果为:Delete class B Delete class A 如果把A的virtual去掉:那就变成了Delete class A也就是说不会删除派生类里的剩余部分内容,也即不调用派生类的虚函数因此在类的继承体系中,基类的析构函数不声明为虚函数容易造成内存泄漏。所以如果你设计一定类可能是基类的话,必须要声明其为虚函数。正如Symbian中的CBase一样。Note:1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了。 2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类。 3. 有虚函数的类,几乎可以确定要有个虚析构函数。 4. 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的。 5. 析构函数的异常退出会导致析构不完全,从而有内存泄露。最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的操作。 6. 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。 7.在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。8. 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分,不能忘记了。
⑸ 析构函数和虚函数的用法和作用
置于“~”是析构函数;析构函数因使用"~"符号(逻辑非运算符),表示它为腻构造函数,加上类名称来定义。
;析构函数也是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载,只有在类对象的生命期结束的时候,由系统自动调用。
有适放内存空间的做用!
虚函数是C++多态的一种表现
例如:子类继承了父类的一个函数(方法),而我们把父类的指针指向子类,则必须把父类的该函数(方法)设为virturl(虚函数)。
使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。
如果父类的函数(方法)根本没有必要或者无法实现,完全要依赖子类去实现的话,可以把此函数(方法)设为virturl
函数名=0
我们把这样的函数(方法)称为纯虚函数。
如果一个类包含了纯虚函数,称此类为抽象类
⑹ c++题,谁解释下
典型的虚析构函数应用问题,在你的例子中,子类的对象并没有被释放,只释放了基类部分,像你这样使用虚函数会出问题,因此最好把基类的析构函数声明为虚拟的,这样才能保证在使用new时,能正确释放资源,下面具体给你介绍一下为什么要使用虚析构函数,以及你的程序为什么没有输出YY吧。看了之后你就能让程序输出YY了。
虚析构函数
1. 为什么需要虚析构函数:当使用new运算符动态分配内存时,基类的析构函数就应该定义为虚析构函数,不然就会出问题。比如类B由类A继承而来,则有语句A *p= new A;delete p; 这时没有问题,调用类A的析构函数释放类A的资源。但如果再把类B的内存动态分配给指针p时如p= new B; delete p;如果基类的析构函数不是虚析构函数的话就会只调用基类A中的析构函数释放资源,而不会调用派生类B的析构函数,这时派生类B的资源没有被释放。
2. 解决这个问题的方法是把基类的析构函数声明为虚析构函数,即在析构函数前加virtual关见字,定义为虚析构函数时当用delete释放派生类的资源时就会根据基类的析构函数自动调用派生类中的析构函数释放派生类的资源。
3. 只要基类中的析构函数是虚析构函数,则该基类的派生类中的析构函数自动为虚析构函数,虽然派生类中的析构函数前没有virtual关见字,析构函数名字也不一样,但派生类中的析构函数被自动继承为虚析构函数。
4. 如果要使用new运算符分配内存,最好将析构函数定义为虚析构函数。
⑺ 在C++中,能否声明虚构函数为什么能否声明虚析构函数为什么
原因如下:在C++-中不能声明虚构造函数,多态是不同的对象对同一消息有不同的行为特性,虚函数作为运行过程中多态的基础,主要是针对对象的,面构造函数是在对盘产生之前运行的,因此虚构造函数是没有童义的。
在C++中可以声明虚析构函数,析构函数的功能是在该类对象消亡之前进行一些必要的清理工作,如果一个类的析构函数是虚函数,那么由它派生而来的所有子类的析构函数也是虚函数。
析构函数设置为虚函数之后,在使用指针引用时可以动态联编,实理运行时的多态,保证使用基类的指针就能够谓用适当的析构函数指针对不同的对象进行清理工作。
(7)为什么虚析构函数名不一样扩展阅读:
虚函数的限制:
1、非类的成员函数不能定义为虚函数,类的成员函数中静态成员函数和构造函数也不能定义为虚函数,但可以将析构函数定义为虚函数。实际上,优秀的程序员常常把基类的析构函数定义为虚函数。
因为将基类的析构函数定义为虚函数后,当利用delete删除一个指向派生类定义的对象指针时,系统会调用相应的类的析构函数。而不将析构函数定义为虚函数时,只调用基类的析构函数。
2、只需要在声明函数的类体中使用关键字“virtual”将函数声明为虚函数,而定义函数时不需要使用关键字“virtual”。
3、当将基类中的某一成员函数声明为虚函数后,派生类中的同名函数(函数名相同、参数列表完全一致、返回值类型相关)自动成为虚函数。
4、如果声明了某个成员函数为虚函数,则在该类中不能出现和这个成员函数同名并且返回值、参数个数、类型都相同的非虚函数。在以该类为基类的派生类中,也不能出现和这个成员函数同名并且返回值、参数个数、类型都相同的非虚函数。
⑻ 关于C++ 类继承中的虚析构函数
你第一个问题的理解是错的,其实只要子类的析构函数是虚函数,子类和基类的析构函数是构成覆盖关系的,因为尽管他们函数名不一样,但因为每个类只有一个析构函数,所以c++规定他们是构成覆盖关系的,所以两全其美的方法就是基类的析构函数都定义为虚函数
⑼ 析构函数为什么是虚函数
析构函数可以为虚函数,也可以不为虚函数。(更多的时候不为虚函数)。设计析构函数为虚函数,主要是考虑到继承。
析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
函数介绍
与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统会自动执行析构函数。以C++语言为例:析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如~stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。
⑽ 请讲一讲析构函数和虚函数的用法和作用。
析构就是对象离开生存空间时执行的,用来清理分配的空间之类.
虚函数的作用:假如有类A.类A派生出类B.
那么如果写A* p = new B;时.就得到了一个指向类B的指针,这个指针的类型是A*
如果类A和类B中都有void Out()这么个函数.p->Out()将调用A::Out()函数
而如果把类A中的改成虚函数virtual void Out().p->Out()就将调用B::Out()函数.
就是这样
下面抄几段:
析构函数是“反向”的构造函数。它们在对象被撤消(回收)时调用。析构函数的名 称除了最前面的“~”符号外,与类的名称相同。例如,类String的析构函数是~string()。 析构函数通常用于当一个对象不再需要时,完成“消除”功能。
在函数中建立对象之后,这个对象作为局部对象开始生存,直到函数运行到遇见右括号“}”才结束生存,此时调用析构函数。
对象的释放发生在以下几种情况,首发自学编程网:
·使用运算符new分配的对象被delete删除。
·一个具有块作用域的本地(自动)对象超出其作用域。
·临时对象的生存期结束。
·程序结束运行。
·使用完全限定名显示调用对象的析构函数。
有几条规则约束着析构函数的说明:
·不能接受参量。
· 不能说明有任何返回类型(包括void)。
·不能用return语句返回值。
· 不能说明为const、volatile或static,但析构函数可以因说明为const、volatile或static的对象的析构而被调用。
·可以说明为虚拟的。使用虚析构函数,可以撤消对象而不必知道该对象的类型。由于使用虚拟函数机制,程序将调用该对象的正确的析构函数。
注意:在一个抽象类中,析构函数可以说明为虚函数。我们会在后面详细介绍虚函数的概念。
虚函数去这看吧
http://www.pconline.com.cn/pce/empolder/gj/c/0507/665004.html
下面还有个虚析构的
http://www.wangchao.net.cn/bbsdetail_431181.html