C++语言基础七

1、析构函数一般写成虚函数的原因

直观的讲:是为了降低内存泄漏的可能性。举例来说就是,一个基类的指针指向一个派生类的对象,在使用完毕准备销毁时,如果基类的析构函数没有定义成虚函数,那么编译器根据指针类型就会认为当前对象的类型是基类,调用基类的析构函数(该对象的析构函数的函数地址早就被绑定为基类的析构函数),仅执行基类的析构,派生类的自身内容将无法被析构,造成内存泄漏。

如果基类的析构函数定义成虚函数,那么编译器就可以根据实际对象,执行派生类的析构函数,再执行基类的析构函数,成功释放内存。

2、构造函数为什么一般不定义为虚函数

  • 虚函数调用只需要知道“部分的”信息,即只需要知道函数接口,而不需要知道对象的具体类型。但是,我们要创建一个对象的话,是需要知道对象的完整信息的。特别是,需要知道要创建对象的确切类型,因此,构造函数不应该被定义成虚函数;
  • 而且从目前编译器实现虚函数进行多态的方式来看,虚函数的调用是通过实例化之后对象的虚函数表指针来找到虚函数的地址进行调用的,如果说构造函数是虚的,那么虚函数表指针则是不存在的,无法找到对应的虚函数表来调用虚函数,那么这个调用实际上也是违反了先实例化后调用的准则。

3、构造函数或析构函数中调用虚函数会怎样

实际上是不应该在构造函数或析构函数中调用虚函数的,因为这样的调用其实并不会带来所想要的效果。

举例来说就是,有一个动物的基类,基类中定义了一个动物本身行为的虚函数action_type(),在基类的构造函数中调用了这个虚函数。

派生类中重写了这个虚函数,我们期望着根据对象的真实类型不同,而调用各自实现的虚函数,但实际上当我们创建一个派生类对象时,首先会创建派生类的基类部分,执行基类的构造函数,此时,派生类的自身部分还没有被初始化,对于这种还没有初始化的东西,C++选择当它们还不存在作为一种安全的方法。

也就是说构造派生类的基类部分时,编译器会认为这就是一个基类类型的对象,然后调用基类类型中的虚函数实现,并没有按照我们想要的方式进行。即对象在派生类构造函数执行前并不会成为一个派生类对象。

在析构函数中也是同理,派生类执行了析构函数后,派生类的自身成员呈现未定义的状态,那么在执行基类的析构函数中是不可能调用到派生类重写的方法的。所以说,我们不应该在构造函数或析构函数中调用虚函数,就算调用一般也不会达到我们想要的结果。

4、析构函数的作用,如何起作用?

构造函数只是起初始化值的作用,但实例化一个对象的时候,可以通过实例去传递参数,从主函数传递到其他的函数里面,这样就使其他的函数里面有值了。规则,只要你一实例化对象,系统会自动调用一个构造函数,就是你不写,编译器也自动调用一次。

析构函数与构造函数的作用相反,用于撤销对象的一些特殊任务处理,可以是释放对象分配的内存空间;特点:析构函数与构造函数同名,但该函数前面加~。

析构函数没有参数,也没有返回值,而且不能重载,在一个类中只能有一个析构函数。当撤销对象时,编译器也会自动调用析构函数。每一个类必须有一个析构函数,用户可以自定义析构函数,也可以是编译器自动生成默认的析构函数。一般析构函数定义为类的公有成员。

5、构造函数的执行顺序?析构函数的执行顺序?

构造函数顺序

  • 基类构造函数。如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序,而不是它们在成员初始化表中顺序。
  • 成员类对象构造函数。如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序
  • 派生类构造函数。

析构函数顺序

  • 调用派生类的析构函数;
  • 调用成员类对象的析构函数;
  • 调用基类的析构函数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值