C++类和对象(中)

系列文章目录

​​​​​​C++类和对象(上)

C++类和对象(下)​​​​​​​



前言

   面向对象编程(Object-Oriented Programming,简称OOP)是一种强大的编程范式,它将数据和操作数据的方法组织成类和对象,使得程序更易于理解、扩展和维护。在C++中,类和对象是OOP的核心概念,为程序员提供了一种结构化的方法来组织和设计代码。本节我们继续来学习C++的类和对象


一.拷贝构造函数函数

拷贝构造函数也是特殊的成员函数

其特征如下:

1. 拷贝构造函数是构造函数的一个重载形式。 

2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。比如这个日期类的拷贝构造

Data(const Data& d);

3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按 字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

在一些简单的类里面,拷贝构造不需要自己写,编译器生成的默认的就可以了,比如这个日期类

class Data
	{
	public:
		Data(int year = 1970, int month = 1, int day = 1);
		Data(const Data& d);
		~Data();

		void Print();
		int GetMonthDay();

	private:
		int _year;
		int _month;
		int _day;
	};

只需要浅拷贝就可以,但比如这个二叉树节点类

class TreeNode
{
public:
	TreeNode(TreeType x);
	int Height();
	~TreeNode();
	void TreeDestroy();
	void InOrder();

private:
	TreeType _val;
	TreeNode* _left;
	TreeNode* _right;
};

        如果使用值拷贝,那么拷贝过去的指向的空间和原指向的空间是一块,在对拷贝的执行销毁后,原先的就不能再使用,并且还会发生对同一块空间释放多次的问题,这时就需要自己写拷贝构造,实现深拷贝,

二.运算符重载

        C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其 返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型 operator操作符(参数列表)

注意:

  1. 不能通过连接其他符号来创建新的操作符:比如operator@
  2. 重载操作符必须有一个类类型参数
  3. 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
  4. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  5. .*     ::    sizeof     ?:    .    注意以上5个运算符不能重载

1.  +  += 运算符重载

Data operator+(int day);
Data& operator+=(int day);

以日期类举例子

+=会使得原对象进行改变,返回值也是原对象,所以使用引用返回提高速率

Data& Data::operator+=(int day)
{
	if (day < 0)
		return *this -= (-day);
	_day += day;
	while (_day > GetMonthDay())
	{
		_day -= GetMonthDay();
		_month += 1;
		if (_month == 13)
		{
			_year += 1;
			_month = 1;
		}
	}
	return *this;
}

加法直接复用+=,加法不改变原对象

Data Data::operator+(int day) const
{
	Data d(*this);
	d += day;
	return d;
}

需要注意加法重载里面,不能返回d的引用,d的生命周期只在函数里面

2.  -   -=运算符重载

类似+=

Data& Data::operator-=(int day)
{
	if (day < 0)
		return *this += (-day);
	_day -= day;
	while (_day<=0)
	{
		_month -= 1;
		if (_month == 0)
		{
			_year -= 1;
			_month = 12;
		}
		_day += GetMonthDay();
	}
	return *this;
}
Data Data::operator-(int day)
{
	Data d(*this);
	d -= day;
	return d;
}

3.逻辑运算符重载

bool operator==(const Data& d) ;
bool operator>=(const Data& d) ;
bool operator<=(const Data& d) ;
bool operator>(const Data& d) ;
bool operator<(const Data& d) ;
bool operator!=(const Data& d) ;

对于日期类比如==

bool Data::operator==(const Data& d)
{
	return _year == d._year && _month == d._month && _day == d._day;
}

其他的都可以相互复用,比如写了>和==就可以在<,<=,>=,!=相互复用

4.流插入流提取操作符重载

        对于流插入和流提取操作符,是多目操作符,根据规定,第一个参数是左边的,第二个参数是右边的,所以流插入和流提取不能写在类里面,在类里面的成员函数会有一个隐含的this指针,默认站定第一个位置,所以我们将其写在全局,比如这个日期类

std::ostream& operator<<(std::ostream& out, const Data& d)
{
	out << d._year <<"/"<< d._month << "/"<< d._day  << std::endl;
	return out;
}
std::istream& operator>>(std::istream& in,  Data& d)
{
	in >> d._year>>d._month>>d._day;
	return in;
}

为了在类外面也能访问成员变量,使用友元

5. 前置和后置  ++  -- 运算符重载

c++规定无参的为前置,带一个int类型参数的是后置.比如这个日期类

Data& operator++();//前置++声明
Data& operator--();//前置--声明
Data operator++(int);//后置++声明
Data operator--(int);//后置--声明

知道这些实现就简单了

三.const成员函数

        将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数 隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。比如这个日期类的this指针的类型是Data* const this; 而使用const成员函数时,这个this指针是const Data* const this;这表示该成员函数承诺不会修改类的成员变量。在 const 成员函数中,对于非静态成员变量,它们都被视为常量,因此在函数体内不能被修改。比如

bool Data::operator==(const Data& d) const
{
	return _year == d._year && _month == d._month && _day == d._day;
}

只是想比较大小,不改变对象,就在成员函数后加上const,const在声明和实现都要加上

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值