文章目录提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
- 前言
- 一、this指针
- 二、类的默认成员函数
- 三、构造函数
- 3.1 构造函数的概念
- 3.2 构造函数的特性
- 四、析构函数
- 4.1 析构函数的概念
- 4.2 析构函数的特性
- 五、拷贝构造函数
- 5.1 拷贝构造函数的概念
- 5.2 拷贝构造函数的特性
- 六、赋值重载函数
- 总结
前言
本文继续上一篇的内容,接着介绍C++的默认成员函数。
一、this指针
在介绍C++的成员函数之前,先介绍一下this指针。我们定义一个日期类Date
class Date
{
public :
void Display ()
{
cout <<_year<< "-" <<_month << "-"<< _day <
_year = year;
_month = month;
_day = day;
}
private :
int _year ; // 年
int _month ; // 月
int _day ; // 日
};
int main()
{
Date d1, d2;
d1.SetDate(2018,5,1);
d2.SetDate(2018,7,1);
d1.Display();
d2.Display();
return 0;
}
二、类的默认成员函数在这个日期类当中,当对象d1调用SetDate时怎么知道是对象d1调用,而不是对象d2调用呢?C++通过this指针解决了该问题。C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
另外this指针有以下几种特性:
① this指针的类型:类类型* const。
②. 只能在“非静态成员函数”的内部使用 。
③. this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
④. this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传递,不需要用户传递。
注意:this指针是成员函数隐藏的参数,在成员函数被调用时,编译器会自动加上。
三、构造函数 3.1 构造函数的概念类的默认成员函数有6个。即构造函数,析构函数,拷贝构造函数,复制重载,普通对象的取地址重载和const对象的取地址重载。我们在这里只介绍前四种,后面两种很少见到。
3.2 构造函数的特性构造函数是一个特殊的成员函数,在对象实例化时自动调用,保证每个对象被实例化出来就是已经初始化过的(他不是开空间创建对象,而是对对象进行初始化)。
①函数名与类名相同,且没有返回值。
②对象实例化的时候自动调用。
③构造函数可以重载(带参的,无参的,全缺省的和我们不写编译器默认生成的)。其中无参的和全缺省的叫做默认构造函数(只有一个)。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。
④我们不写,编译器默认生成的构造函数。编译器自己生产的构造函数对内置类型(int,char,double,指针,数组等)不处理,对自定义类型(struct,class)会调用自己的构造函数。
注意:C++的构造函数对自定义类型和内置类型没有统一处理,所以有的时候构造函数需要我们自己实现。如:日期类的构造函数。
为了方便理解,通过以下几个例子说明一下。
class Date
{
int _year;
int _month;
int _day;
//对于日期类这种需要我们自己实现构造函数,因为默认生成的构造函数对内置类型不处理
}
//栈实现队列
class Queue
{
Stack_PushST;
Stack_PopST;
//对于这种类我们不需要自己实现构造函数,因为默认生成的就够用了。
}
四、析构函数
4.1 析构函数的概念
4.2 析构函数的特性析构函数也是一个特殊的成员函数,与构造函数功能相反,析构函数不是完成对象的销毁,而是在对象销毁时调用析构函数来清理申请的空间。
①函数名在类名前加~,且没有返回值。
②对象生命周期结束时自动调用。
③我们不写,编译器默认生成的析构函数。编译器自己生产的析构函数对内置类型(int,char,double,指针,数组等)不处理,对自定义类型(struct,class)会调用自己的析构函数。
为了方便理解,通过以下几个例子说明一下。
class Date
{
int _year;
int _month;
int _day;
//对于日期类这种不需要我们自己实现析构函数,因为没有资源需要清理
}
class Stack
{
int *a;
int _top;
int _capacity;
//需要我们自己实现,有资源需要清理
}
class Queue
{
Stack_PushST;
Stack_PopST;
//不需要自己实现,默认生成的够用了
}
五、拷贝构造函数
5.1 拷贝构造函数的概念
5.2 拷贝构造函数的特性只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。
①拷贝构造函数是构造函数的函数重载(函数名跟类名相同)。
② 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用(如果使用传值的话,传值就是一次拷贝构造,会无限套娃引发无穷递归)。
③如果我们不写,编译器会默认生成一份。默认生成的拷贝构造对内置类型进行按字节序的值拷贝(浅拷贝),对自定义类型调用自己的拷贝构造。
总结:默认生成的拷贝构造对内置类型和自定义类型都处理,但是他们处理的细节不一样。 为了方便理解,通过以下几个例子说明一下。
class Date
{
int _year;
int _month;
int _day;
//不需要我们自己实现,默认生成的拷贝构造对内置类型完成值拷贝就可以满足要求
}
class Stack
{
int *a;
int _top;
int _capacity;
//需要我们自己实现深拷贝(以后讲),默认生成的拷贝构造对内置类型完成值拷贝,在数组a的空间析构时会被释放两次
}
class Queue
{
Stack_PushST;
Stack_PopST;
//不需要自己实现,默认生成的够用了
}
六、赋值重载函数
C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
注意:
①作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参。
②注意以上5个运算符不能重载(.* 、:: 、sizeof 、?: 、. ),不能重载内置类型的运算来改变其含义。
③检查自己给自己赋值。
④ 一个类如果没有显式定义赋值运算符重载,编译器也会生成一个。对内置类型完成按字节序的值拷贝,对自定义类型会去调用自己的赋值重载。
总结:默认生成的赋值重载对内置类型和自定义类型都处理,但是他们处理的细节不一样。 为了方便理解,通过以下几个例子说明一下。
class Date
{
int _year;
int _month;
int _day;
//不需要我们自己实现,默认生成的赋值重载就可以满足要求
}
class Stack
{
int *a;
int _top;
int _capacity;
//需要我们自己实现赋值重载,默认生成的赋值重载对内置类型完成值拷贝,在数组a的空间析构时会被释放两次
}
class Queue
{
Stack_PushST;
Stack_PopST;
//不需要自己实现,默认生成的够用了
}
总结
本文主要介绍了this指针和类的默认成员函数及其一些注意事项。



