构造函数和析构函数可以是虚函数吗

构造函数和析构函数可以是虚函数吗,第1张

构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。不建议在构造函数和析构函数里面调用虚函数。构造函数不能声明为虚函数的原因是:1 构造一个对象的时候,必须知道对象的实际类型,而虚函数行为是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功。编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。。。2 虚函数的执行依赖于虚函数表。而虚函数表在构造函数中进行初始化工作,即初始化vptr,让他指向正确的虚函数表。而在构造对象期间,虚函数表还没有被初 始化,将无法进行。虚函数的意思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。析构函数设为虚函数的作用: 解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针delete时,如果不定义成虚函数,派生类中派生的那部分无法析构。 例:#include "stdafxh"#include "stdioh"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 BDelete class A如果把A的virtual去掉:那就变成了Delete class A也就是说不会删除派生类里的剩余部分内容,也即不调用派生类的虚函数因此在类的继承体系中,基类的析构函数不声明为虚函数容易造成内存泄漏。所以如果你设计一定类可能是基类的话,必须要声明其为虚函数。正如Symbian中的CBase一样。Note:1 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了。2 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类。3 有虚函数的类,几乎可以确定要有个虚析构函数。4 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的。5 析构函数的异常退出会导致析构不完全,从而有内存泄露。最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的 *** 作。6 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。7在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。8 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分,不能忘记了。

析构函数使用virtual的前提是,当一个指向基类的指针,实际指向派生类的实例,这时销毁这个基类指针,可以调用派生类的析构函数。 但如果是私有派生,那就不能用指向基类的指针,来指着派生类的实例。换句话说,这个派生类必须用自己的名义销毁,所以不必将析构函数声明为虚函数。

如果析构函数不是虚函数的话,那么当用基类指针 *** 作派生类的对象的话,析构的时候会调用基类的析构函数,从而导致派生类无法被正确析构。用虚函数则可以避免这种情况,无论指针类型是什么,总能够找到适合对象类型的析构函数。

这个话题你可以看看effective c++,里面讲的更加详细

一句话:避免内存泄露。

比如:

class Base

{

public:

Base(){m_p1=new int(1);}

~Base(){delete m_p1;}

protected:

int m_p1;

};

class Derive:public Base

{

public:

Derive(){m_p2=new int(2);}

~Derive(){delete m_p2;}

private:

int m_p2;

};

int main()

{

Base pDerive=new Derive;

delete pDerive;

return 0;

}

上面的程序将产生内存泄露,因为只会调用Base的析构函数,而不会调用Derive的析构函数。

如果把析构函数都改为虚析构函数,则上面的Bug可Fix。

原因如下:在C++-中不能声明虚构造函数,多态是不同的对象对同一消息有不同的行为特性,虚函数作为运行过程中多态的基础,主要是针对对象的,面构造函数是在对盘产生之前运行的,因此虚构造函数是没有童义的。

在C++中可以声明虚析构函数,析构函数的功能是在该类对象消亡之前进行一些必要的清理工作,如果一个类的析构函数是虚函数,那么由它派生而来的所有子类的析构函数也是虚函数。

析构函数设置为虚函数之后,在使用指针引用时可以动态联编,实理运行时的多态,保证使用基类的指针就能够谓用适当的析构函数指针对不同的对象进行清理工作。

扩展资料:

虚函数的限制:

1、非类的成员函数不能定义为虚函数,类的成员函数中静态成员函数和构造函数也不能定义为虚函数,但可以将析构函数定义为虚函数。实际上,优秀的程序员常常把基类的析构函数定义为虚函数。

因为将基类的析构函数定义为虚函数后,当利用delete删除一个指向派生类定义的对象指针时,系统会调用相应的类的析构函数。而不将析构函数定义为虚函数时,只调用基类的析构函数。

2、只需要在声明函数的类体中使用关键字“virtual”将函数声明为虚函数,而定义函数时不需要使用关键字“virtual”。

3、当将基类中的某一成员函数声明为虚函数后,派生类中的同名函数(函数名相同、参数列表完全一致、返回值类型相关)自动成为虚函数。

4、如果声明了某个成员函数为虚函数,则在该类中不能出现和这个成员函数同名并且返回值、参数个数、类型都相同的非虚函数。在以该类为基类的派生类中,也不能出现和这个成员函数同名并且返回值、参数个数、类型都相同的非虚函数。

-虚函数

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/11679967.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-17
下一篇 2023-05-17

发表评论

登录后才能评论

评论列表(0条)

保存