在上一篇博客中,和大家分享了C++中类和对象的定义,类的大小的计算等知识,那么如果C++中一个自定义类中不定义任何的成员变量和成员函数,那么这个类中就是一个什么都没有的空类了吗?实际上,如果在一个类中,如果类中什么成员都不定义,编译器会自动生成6个默认成员函数。
接下来借助一个自定义MyDate自定义日期类详细说明C++类中的各个默认成员函数。
默认成员函数:
1.默认成员函数定义:
如果类中未显式定义,编译器会自动生成的成员函数,即为默认成员函数。
2.默认成员函数构成:
C++中类的默认成员函数有:构造函数、析构函数、拷贝构造函数、赋值重载函数、取地址重载(普通对象取地址重载、const对象取地址重载)。
3.各成员函数详解:
3.1构造函数:
作用:初始化类对象成员属性。即实例化一个类对象后,给对象的成员属性赋初值。
特征:
- 函数名是类名
- 无返回值
- 创建对象时自动调用
- 构造函数可以重载,即对象成员有多种初始化形式
例如:MyDate类的构造函数,实现实例化一个MyDate类对象时,对各个成员初始化。
类型:
构造函数支持重载,所以可以实现多种形式的类的构造函数。例如:对MyDate类,还可以提供其他形式的构造函数。也可以用缺省参数实现构造函数。
带参构造函数:
全缺省构造函数:
通过上例可以看出,构造函数实际上起到的是初始化成员属性的作用,构造函数特殊之处有两个,一、实例化对象时,构造函数自动调用。二、如果我们没有实现类的构造函数,编译器会自动生成一个构造函数。但是一旦我们实现了任意一种格式的构造函数,编译器就不会自动生成了。
如上图,当我们实现了构造函数时,实例化时自动调用,无需显式调用,即可初始化。
如上图,如果我们未实现构造函数,则编译器自动生成一个构造函数,但是在监视窗口中可以看到d1成员属性并未初始化,而是随机值,这是因为编译器自动生成的构造函数对内置类型成员不处理,所以此时d1的year_、month_、day_属性均未初始化。
C++中成员类型:
内置类型:语言提供的类型,例如:int、char、所有类型的指针...
自定义类型:利用class或者struct关键字自己定义的类。
我们未实现构造函数,编译器自动生成的构造函数,对内置类型不处理,对自定义类型调用其默认构造函数。
易混淆概念:
默认构造函数:默认构造函数是指无需传参的构造函数,包括无参构造,全缺省的构造函数,编译器自动生成的构造函数。
默认构造函数在无参实例化时不能同时存在,原因是调用存在歧义。
默认成员函数:类中的特殊成员函数,程序员未实现时,由编译器自动生成。
针对编译器默认生成的默认构造函数对内置类型成员属性不处理,C++11给出了补丁,即可以在声明成员属性时给出缺省值。如下图,即在声明时给出缺省值,实现自动生成的构造函数也可以对内置类型成员处理。
特殊强调:
构造函数的作用:不是创建一个类对象,而是初始化类对象成员。
3.2析构函数:
定义:
类默认成员函数之一,完成类对象的资源清理工作。
注意:是完成资源清理工作,而非销毁对象。
特征:
- 函数名是类名前面加一个“~”
- 无返回值
- 没有参数,析构函数不能重载
- 对象生命周期结束时,由编译器自动调用析构函数
- 如果程序员未实现,由编译器自动生成,对内置类型不处理,自定义类型调用其析构函数。
3.3拷贝构造函数
定义:
拷贝构造函数也是构造函数的一种,同时也是C++类的默认成员函数。
作用:
可以实现利用一个已有的类对象,初始化实例化出来的一个新的类对象。
特征:
- 拷贝构造函数是构造函数的一种,函数名为类名,没有返回值
- 参数必须是类对象的引用,如果使用传值传参,则会引发无穷递归。
- 拷贝构造作为默认成员函数,如果我们不实现,编译器会自动实现,针对内置类型成员属性进行浅拷贝(值拷贝),针对自定义类型成员属性,调用该类的拷贝构造。
拷贝构造的使用场景:
- 使用已有的对象初始化实例化的一个新的类对象。自动调用拷贝构造
- 函数调用时,使用类对象作为参数。自动调用拷贝构造
- 函数有返回值时,使用类对象作为函数返回值。自动调用拷贝构造
- 即只要发生拷贝构造一个自定义类的动作,就必须通过调用这个类的拷贝构造函数来实现
函数调用书写格式:以MyDate类对象为例
1.使用已有对象创建初始化一个新的类对象,利用已有的d1对象初始化新的MyDate对象d2(两种书写格式)
MyDate d1;
MyDate d2(d1);
MyDate d2=d1;
3.4赋值重载
介绍赋值重载前,首先介绍一个新的概念-运算符重载。为使自定义类能够像内置类型一样使用一些常见的运算符,C++中引入了运算符重载的概念。运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名:关键字operator 需要重载的运算符符号。
函数通式:返回值类型 operator操作符(参数列表)
注意点:
- 函数调用的方法:对象可以直接使用重载的符号,根据符号的类型(单目,双目)等传入相关参数,也可以使用operator重载符号(参数) 的形式来调用函数,运算符重载函数作为成员函数调用时,单目运算符的操作数即为调用函数的对象,双目运算符的左操作数默认为调用函数的类对象,右操作数可利用参数传入。
以MyDate类为例,重载”==“比较运算符。
class MyDate {
private:
int year_;
int month_;
int day_;
public:
bool operator==(const MyDate& d)
{
return year_ == d.year_ && month_ == d.month_ && day_ == d.day_;
}
MyDate(int year = 2000, int month = 1, int day = 1)
{
year_ = year;
month_ = month;
day_ = day;
}
};
int main()
{
MyDate d1;
MyDate d2(2000, 1, 1);
cout << (d1 == d2) << endl;//注意<< ==运算符的优先级
return 0;
}
- 重载操作符必须有一个类类型参数
- 用于内置类型的运算符,其含义不能改变
- 作为类成员函数重载时,其形参看起来比操作数数目少1
- .* :: sizeof ?: . 以上五个运算符不能重载
默认成员函数-赋值重载即实现赋值符号的重载”=“
注意点:
- 赋值运算符只能重载成成员函数不能重载成全局函数
- 作为类的默认成员函数,赋值重载如果没有显式实现,编译器会自动生成,对内置类型成员,直接赋值,自定义类型的成员调用对应的赋值重载函数完成赋值。
- 涉及到资源管理时,简单的赋值存在问题,需要我们自己实现赋值重载。
3.5取地址以及const取地址操作符重载
返回this指针,即指向对象(const对象)的指针
编译器可以自动生成。
以上就是本片博客的全部内容,本片博客主要向大家分享了C++中类的6个默认成员函数,如果文章有不当之处或者错误欢迎在评论区指正或者私信小Q,希望能对大家的学习有所帮助,下期见!^-^