构造函数:值的初始化,可带参数,无返回值,可重载,可存在多个
析构函数:释放对象内存空间,无参数,无返回值,不可重载,只能存在一个
拷贝构造函数:拷贝对象,其形参必须是引用
1.空类会默认添加哪些东西?怎么写?空类的大小是多少?为什么?
1)Empty():默认构造函数
2)Empty(const Empty&):拷贝构造函数
3)~Empty():析构函数
4)Empty& operate=(const Empty&):赋值运算符
空类的大小为1,因为C++要求类的每个实例必须具有独一无二的地址,编译器自动为空类分配一个字节的大小,这样保证了每个实例具有独一无二的内存地址
2.构造函数的执行顺序?析构函数的执行顺序
构造函数:
1)父类构造函数,如果有多个父类,则这些父类的构造函数的调用顺序为父类在子类中出现的顺序
2)成员类对象构造函数,如果有多个成员类,则这些成员类的构造函数调用顺序为成员类在类中被声明的顺序
3)子类构造函数
析构函数:
1)子类析构函数
2)成员类对象的析构函数
3)父类的析构函数
3.构造函数和析构函数中可以抛异常吗?
不建议在构造函数中抛异常,不可以在析构函数中抛异常!
1)在构造函数中抛异常,将会导致析构函数不被执行,会造成内存泄漏,需要手动去释放内存或者采用auto_ptr智能指针:因为构造函数中抛出异常会默认构造函数没有执行完毕,析构函数也就不会被调用,从而内存泄漏
2)在析构函数中抛异常,异常的处理又是调用异常对象的析构函数,这样会陷入无穷的递归中,所以必须把异常封装在析构函数的内部,而不是将异常抛出去
4.类成员的初始化方式?哪种更快?为什么?
1)赋值初始化:在构造函数中做赋值操作,是在数据成员分配好内存空间之后再进行赋值操作
2)列表初始化:在冒号后使用初始化列表,是在数据成员分配内存空间时就进行初始化
列表初始化更快:赋值操作会产生临时对象,临时对象的出现会降低程序效率
5.如何阻止编译器自动生成拷贝构造函数和赋值函数并且避免被调用?
1)将拷贝构造函数和赋值函数手动重写并且设置为privte,且只进行声明不予实现
手动重写可以避免编译器默认生成,设置为private可以避免被外部类或子类调用,只声明不实现可以在本类的成员函数和友元函数调用时产生连接错误
2)继承Uncopyable类
Uncopyable类的拷贝构造函数和赋值运算符都是私有的,不会被子类调用,从而可以阻止拷贝和对象赋值
3)手动重写并且将函数定义为deleted函数:deleted函数为禁止调用函数
6.什么情况下会生成默认构造函数?
1)类成员含有构造函数时:为了能够调用类成员的构造函数,所以本类必须要有构造函数
2)父类中含有构造函数时:为了能够调用父类的构造函数,所以子类必须有构造函数才能调用父类的构造函数,才能初始化父类成员
3)类中含有虚函数时:对象的虚函数表指针需要通过构造函数进行初始化
4)虚继承时:指向虚基类的指针要在构造函数中被初始化
构造函数只有在被需要时才会自动生成!
编译器生成构造函数和拷贝构造函数的情况是一样的,也就是说编译器合成拷贝构造函数也是在上面四种情况下
7.类的析构函数什么时候会被调用?
1)对象生命周期结束时
2)delete指向对象的指针时,或delete指向对象的基类类型指针,而基类析构函数是虚函数时
3)对象A是对象B的成员,B的析构被调用时,A的析构函数也会被调用
8.为什么友元函数必须在类的内部进行声明?
因为编译器在编译类的时候就必须知道谁可以访问类的私有部分!所以友元函数必须在类的内部进行声明,可以在类的外部进行定义!