构造&析构函数
构造函数
定义:与类同名,可以有参可以无参,主要功能用于在类的对象创建时定义初始化的状态,无返回值,也不能用void修饰,构造函数不能被直接调用,必须通过new运算符在创建对象时才会自动调用
一个类若是只定义了私有的构造函数,将无法通过new关键字来创建其对象,若是没有定义,那么编译器会提供一个默认的构造函数,构造函数可以有多个,
构造列表:即构造函数初始值列表,在构造列表中的变量是直接初始化,在函数体内的则是先调用默认构造函数初始化再赋值,这不仅事关底层效率问题,更重要的是一些数据成员必须初始化,
在构造函数初始化顺序与它们在类定义中的出现顺序保持一致,一般来说初始化的顺序没什么特别要求,不过如果一个成员是用另一成员来初始化的,那么这两个成员的初始化顺序就很重要了
如果可能,尽量避免用一个值来初始化另一个值
explicit 修饰的构造函数必须显示调用,另外修饰的函数不能进行隐式转换。在C++中如果定义了参数列表中的参数,但是在函数内部却没有使用到,那么编译器会报参数没有使用的警告,
拷贝构造函数
定义:以同型对象初始化自我对象,一般类都会定义一个拷贝构造函数,一个拷贝构造函数,一个拷贝分配操作符,即使不需要也会定义为私有的不实现,以防编译器自己定义
class Widget{
public: //这里设置为public,是因为这里要使用,其他情况一般都设为private,且不实现
Widget(); //default构造函数
Widget (const Widget &rhs); //copy构造函数
Widget &operator = (const Widget &rhs); //拷贝分配操作符,一般要返回一个指针的,不强制要求
...
}
Widget w1; //调用default构造函数
Widget w2(w1); //调用拷贝构造函数
w1 = w2; //调用分配操作符
Widget w3 = w2; //调用拷贝构造函数,注意区分与拷贝赋值的关系
析构函数
定义:与构造函数相反,当对象结束其生命周期时,系统自动执行析构函数,析构函数与构造函数名相同,只是在函数名前加~以示区别,析构函数只有一个,不能重载,如果用户并没有定义,那么
编译器也会自动生成一个缺省的析构函数,不要在析构函数中调用exit(),因为析构函数本身即会调用,若是主动调用exit(),则会陷入无限循环,由于析构函数能够自动进行类缺省的清理工作,
如果调用成员或基类的析构函数一样,所以通常并不需要在析构函数的定义中显示地编写任何代码
使用:一般情况下我们不直接调用析构函数,而如果我们需要调用析构函数里面的功能,那么建议将此功能写成一个普通的函数
创建子类对象:此对象先调用基类的构造函数构造对象的基类部分,再调用子类的构造函数构造对象的子类部分
销毁子类对象:此对象先调用子类的析构函数析构对象的子类部分,再调用基类的析构函数析构对象的基类部分
总结:可以想象一下, 子类对象可以访问父类,如果在构造子类对象的子类部分时基类没构建完成,而子类就调用了基类的东西,那么肯定会出问题,所以构造要先构造对象的基类部分
同理,析构时如果先析构子类对象的基类部分,那么在基类析构完成后子类如果再调用基类,那么也会出问题,所以析构要先析构对象的子类部分,就像盖楼从基层盖起,拆楼从顶层拆起
友元函数
定义:形如friend func1();使普通函数能够访问类的友元,实现位置可以在类外或类中,实现代码与普通函数相同,友元关系不能被继承,是单向,不具有交换性,在实现类之间数据共享时减少系统开销,
提高效率等
优点:能够提高效率,表达简单,清晰
缺点:友元破坏了封装机制,尽量不使用友元
声明:放在类的公有区和私有区都没有关系
使用:1. 运算符重载的某些场合需要使用友元 2. 两个类要共享数据的时候
实例:class INTEGER {
friend void A::Print(const INTEGER &obj); //声明这个类的友元函数,那么在其他地方调用这个函数就可以访问类的所有内容,声明时必须明确指出该成员函数属于哪个类
friend class A; //声明友元类
};
void Print(const InteGER &obj) {函数体}
void main() {
INTEGER obj;
Print(obj); // 调用友元函数
}
可以在一个头文件或源文件中定义多个类,然后将它们声明为各自的友元类,在源文件定义各自类中的函数时需要加域作用符
在声明为某个类的友元之前,其必须是程序中的一个已经定义过的类,不能新声明一个类,然后说它是谁谁谁的友元
public:void initialize();
friend void g(X*, int); // Global friend
friend void Y::f(X*); // Struct member friend
friend struct Z; //Entire struct is a friend
friend void h();
friend calss class-name
new 和 delete
C++的new和delete比C中的malloc和free要好得多,C++把创建一个对象所需的所有动作都结合在一个称为new的运算符里,当使用new创建一个对象时,它就在堆里为对象分配内存并为这块内存调用
构造函数进行初始化,默认的new还进行检查以确信在传递地址给构造函数之前分配内存是成功的,所以不必显示地确定调用是否成功, Mytype *fp = new Mytype;只是一个简单的表达式,它带有
内置的长度计算,类型转换,和安全检查,delete只用于删除由new创建的对象,如果是malloc或其他方式创建一个对象,然后由delete删除它,这个动作行为是未定义的,因为大多数默认的
new和delete实现机制都使用了malloc和free,所以很可能会没有调用析构函数就释放了内存,如果正在删除的对象指针是0(即是空,NULL),则不会发生任何事情,因此建议在删除指针后把指针赋为空
以免二次删除,对一个对象二次删除可能会产生某些问题
关于作者
姓名:张坤武
邮箱:1498462303@qq.com