C++-类和对象(2)默认成员函数

时间:2024-01-26 08:02:05

在上一篇博客中,和大家分享了C++中类和对象的定义,类的大小的计算等知识,那么如果C++中一个自定义类中不定义任何的成员变量和成员函数,那么这个类中就是一个什么都没有的空类了吗?实际上,如果在一个类中,如果类中什么成员都不定义,编译器会自动生成6个默认成员函数

接下来借助一个自定义MyDate自定义日期类详细说明C++类中的各个默认成员函数。

C++-类和对象(2)默认成员函数_构造函数

默认成员函数:

1.默认成员函数定义:

如果类中未显式定义,编译器会自动生成的成员函数,即为默认成员函数。

2.默认成员函数构成:

C++中类的默认成员函数有:构造函数析构函数拷贝构造函数赋值重载函数取地址重载(普通对象取地址重载、const对象取地址重载)。


C++-类和对象(2)默认成员函数_析构函数_02

3.各成员函数详解:

3.1构造函数:

作用:初始化类对象成员属性。即实例化一个类对象后,给对象的成员属性赋初值。

特征:

  • 函数名是类名
  • 无返回值
  • 创建对象时自动调用
  • 构造函数可以重载,即对象成员有多种初始化形式

C++-类和对象(2)默认成员函数_成员函数_03

例如:MyDate类的构造函数,实现实例化一个MyDate类对象时,对各个成员初始化。

类型:

构造函数支持重载,所以可以实现多种形式的类的构造函数。例如:对MyDate类,还可以提供其他形式的构造函数。也可以用缺省参数实现构造函数。

带参构造函数:

C++-类和对象(2)默认成员函数_构造函数_04

全缺省构造函数:

C++-类和对象(2)默认成员函数_拷贝构造_05

通过上例可以看出,构造函数实际上起到的是初始化成员属性的作用,构造函数特殊之处有两个,一、实例化对象时,构造函数自动调用。二、如果我们没有实现类的构造函数,编译器会自动生成一个构造函数。但是一旦我们实现了任意一种格式的构造函数,编译器就不会自动生成了。

C++-类和对象(2)默认成员函数_默认成员函数_06

如上图,当我们实现了构造函数时,实例化时自动调用,无需显式调用,即可初始化。

C++-类和对象(2)默认成员函数_拷贝构造_07

如上图,如果我们未实现构造函数,则编译器自动生成一个构造函数,但是在监视窗口中可以看到d1成员属性并未初始化,而是随机值,这是因为编译器自动生成的构造函数对内置类型成员不处理,所以此时d1的year_、month_、day_属性均未初始化。

C++中成员类型:

内置类型:语言提供的类型,例如:int、char、所有类型的指针...

自定义类型:利用class或者struct关键字自己定义的类。

我们未实现构造函数,编译器自动生成的构造函数,对内置类型不处理,对自定义类型调用其默认构造函数。

易混淆概念:

默认构造函数:默认构造函数是指无需传参的构造函数,包括无参构造,全缺省的构造函数,编译器自动生成的构造函数。

默认构造函数在无参实例化时不能同时存在,原因是调用存在歧义。

默认成员函数:类中的特殊成员函数,程序员未实现时,由编译器自动生成。

针对编译器默认生成的默认构造函数对内置类型成员属性不处理,C++11给出了补丁,即可以在声明成员属性时给出缺省值。如下图,即在声明时给出缺省值,实现自动生成的构造函数也可以对内置类型成员处理。

C++-类和对象(2)默认成员函数_析构函数_08

特殊强调:

构造函数的作用:不是创建一个类对象,而是初始化类对象成员。

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,希望能对大家的学习有所帮助,下期见!^-^