构造函数和析构函数

前言

在学习重载的时候遇到了一些构造函数和析构函数的不确定问题,故记录一下

1、关于重载

构造函数允许重载,所以在实例化对象的时候,可以根据传入参数的不同选择不同的构造函数,但是只会执行其中的一个,具体执行哪一个,按照传入的参数。

析构函数:类名作为函数名,在前面加上~。析构函数不允许重载,并且析构函数无参

2、关于定义成虚函数

构造函数不能声明为虚函数,析构函数可以声明为虚函数,而且有时是必须声明为虚函数。
不建议在构造函数和析构函数里面调用虚函数。

构造函数不能声明为虚函数的原因是:

输出结果为:

Delete class B

Delete class A

  1. 如果我们定义了一个构造函数,编译器就不会再为我们生成默认构造函数了。
  2. 编译器生成的析构函数是非虚的,除非是一个子类,其父类有个虚析构,此时的函数虚特性来自父类。
  3. 有虚函数的类,几乎可以确定要有个虚析构函数。
  4. 如果一个类不可能是基类就不要申明析构函数为虚函数,虚函数是要耗费空间的。
  5. 析构函数的异常退出会导致析构不完全,从而有内存泄露。最好是提供一个管理类,在管理类中提供一个方法来析构,调用者再根据这个方法的结果决定下一步的操作。
  6. 在构造函数不要调用虚函数。在基类构造的时候,虚函数是非虚,不会走到派生类中,既是采用的静态绑定。显然的是:当我们构造一个子类的对象时,先调用基类的构造函数,构造子类中基类部分,子类还没有构造,还没有初始化,如果在基类的构造中调用虚函数,如果可以的话就是调用一个还没有被初始化的对象,那是很危险的,所以C++中是不可以在构造父类对象部分的时候调用子类的虚函数实现。但是不是说你不可以那么写程序,你这么写,编译器也不会报错。只是你如果这么写的话编译器不会给你调用子类的实现,而是还是调用基类的实现。
  7. 在析构函数中也不要调用虚函数。在析构的时候会首先调用子类的析构函数,析构掉对象中的子类部分,然后在调用基类的析构函数析构基类部分,如果在基类的析构函数里面调用虚函数,会导致其调用已经析构了的子类对象里面的函数,这是非常危险的。
  8. 记得在写派生类的拷贝函数时,调用基类的拷贝函数拷贝基类的部分,不能忘记了。

    4、抛出异常

  • 1.析构函数不应该抛出异常;
  • 2.当析构函数中会有一些可能发生异常时,那么就必须要把这种可能发生的异常完全封装在析构函数内部,决不能让它抛出函数之外;
  • 3.析构函数异常相对要复杂一些,存在一种冲突状态,程序将直接崩溃:异常的被称为“栈展开(stack unwinding)”的过程中时,从析构函数抛出异常,C++运行时系统会处于无法决断的境遇,因此C语言担保,当处于这一点时,会调用terminate()来杀死进程。因此,当处理另一个异常的过程中时,不要从析构函数抛出异常, 抛出异常时,其子对象将被逆序析构