栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【C++复习】1、拷贝构造函数 2、赋值运算符重载3、const成员

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C++复习】1、拷贝构造函数 2、赋值运算符重载3、const成员

文章目录
  • 1、拷贝构造函数
  • 2、赋值运算符重载
  • 3、const成员

1、拷贝构造函数

什么是拷贝构造函数?
构造函数只有单个形参,该形参是对本类类型对象的引用(一般用const修饰),在用已存在的类类型创建新对象时由编译器自动调用。
拷贝构造函数的特点
1.拷贝构造函数时构造函数的一个重载形式
2.拷贝构造函数的参数只有一个且必须使用引用传参,使用传值会引发无穷递归调用
3.若未显示定义,系统生成默认的拷贝构造函数。
对内置类型成员,默认的拷贝构造函数会完成按字节序的拷贝,这种拷贝我们叫做浅拷贝或值拷贝。
对于自定义类型,会调用它的默认拷贝构造函数。
4.编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,我们还需要自己实现吗?

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
using namespace std;

class String
{
private:
	char* _str;
public:
	String(const char* str = "jack")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	~String()
	{
		cout << "~string()" << endl;
		free(_str);
	}
};
int main()
{
	String s1("hello");
	String s2(s1);
}

以上程序会崩溃。s2为s1的复制,会调用默认的拷贝构造函数。默认的拷贝构造函数只是简单的把两个对象的指针做赋值运算,他们指向的是同一块地址。但是产生两次析构,释放同一块内存而引发程序崩溃。因此需要我们自己实现深拷贝的拷贝构造函数。

2、赋值运算符重载

什么是运算符重载
C++为了增强代码的可读性引入运算符重载,运算符重载是具有特殊函数名的函数,也具有返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通函数类似。
函数名:关键字operator后边接需要重载的运算符符号
函数原型:返回值类型operator操作符(参数列表)
注意:
不能通过其他连接符号来创建新的操作符:比如operator@
重载操作符必须有一个类类型或者枚举类型的操作数
用于内置类型的操作数,其含义不能改变,例如:内置的整型+,不能改变其含义
作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数操作符有一个默认的形参this,限定为第一个形参
.*,::,sizeof,?:,.注意以上5个运算符不能重载
下边的代码对==进行了重载

#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
class Date
{
public:
	Date(int year = 1990, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
//private:
	int _year;
	int _month;
	int _day;
};
bool operator==(const Date& d1, const Date& d2)
{
	return d1._year == d2._year&&d1._month == d2._month&&d1._day == d2._day;
}
int main()
{
	Date d1(2018, 10, 10);
	Date d2(2018, 10, 10);
	cout << operator==(d1, d2)< 

以上代码对==运算符进行了重载,但是我们发现运算符重载成全局的就需要成员变量是共有的,这样会破坏了封装性。可以使用友元函数来解决,或者直接重载成成员函数。

//重载为成员函数
#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
class Date
{
public:
	Date(int year = 1990, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//需要注意的是,左操作数是this指向的调用函数的对象
	bool operator==(const Date& d2)
	{
		return _year == d2._year&&_month == d2._month&&_day == d2._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2018, 10, 10);
	Date d2(2018, 10, 10);
	cout << (d1 == d2) << endl;
}

赋值运算符的特点
1.参数类型为常量引用
2.返回值类型为类类型的引用
3.检测是否自己给自己赋值,如果是则不进行赋值操作
4.返回this
5.如果一个类没有显示定义赋值运算符重载,编译器会生成一个,完成对象按字节序的值拷贝
那么编译器生成的默认赋值重载函数可以完成字节序的值拷贝了,我们还需要自己实现吗?

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
using namespace std;

class String
{
private:
	char* _str;
public:
	String(const char* str = "jack")
	{
		_str = (char*)malloc(strlen(str) + 1);
		strcpy(_str, str);
	}
	~String()
	{
		cout << "~string()" << endl;
		free(_str);
	}
};
int main()
{
	String s1("hello");
//	String s2(s1);
	String s2("nihao");
	s1 = s2;

}

s2赋值给s1之后,他们指向的是同一块地址空间,但是被析构两次,所以会引起程序崩溃。需要使用深拷贝来解决该问题。

3、const成员

const修饰类的成员函数
将const修饰的类成员函数称为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
取地址及const取地址操作符重载
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况才需要重载,如想让别人获取到指定的内容

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1008400.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号