简单的C++:【运算符重载】新手易学

文章介绍了C++中的运算符重载机制,特别是如何使用运算符重载实现自定义类型的输入/输出流操作。通过一个Student类的例子,展示了如何定义并使用友元函数来重载<<运算符,使得可以使用cout<<s1的方式来打印Student对象的信息。此外,文章还提及了运算符重载的一些规则和限制,以及它在处理自定义类型如日期类时的重要性。
摘要由CSDN通过智能技术生成

学过C语言的同志们应该都知道位运算符>> 和 << (右移左移),但是这两个运算符在C++中还是我们的输入和输出流操作符,那么这是为什么呢?,了解完本篇文章之后,我们再来回答这个问题。

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

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

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

但是

不能通过连接其他符号来创建新的操作符:比如operator@

重载操作符必须有一个类类型参数 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义

作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐 藏的this

.*  ::  sizeof   ?:   .   注意以上5个运算符不能重载

假设我们定义了如下的一个学生类,包含的有学生的年龄,学号,和名字。

#include <iostearm>
#include <string.h>
using namespace std;

class Student
{
public:
	Student(int age, int id, const char* name)
	{
		_age = age;
		_id = id;
		_name = new char[strlen(name) + 1];
		//const传给非const的类型是不被允许的,通过开辟新的空间拷贝的方式去实现_name
		strcpy(_name, name);
	}

	~Student()
	{
		_age = _id = 0;
		delete[] _name;
		_name = nullptr;
	}

	void print()
	{
		cout << _age << " " << _id << " " << _name << endl;
	}
private:
	int _age;
	int _id;
	char* _name;
};

int main()
{
	Student s1(18, 12345, "zhangsan");
	s1.print();

	return 0;
}

对于自定义类型我们是不能直接使用标准输出cout打印信息的,如下所示:

必须再写一个专门的打印函数。(如果成员变量是public,那么也可以通过直接访问内部成员变量的方式去打印)。

调用该函数去实现相应的功能:

 那么如果我们现在就是想要通过cout<<s1来实现打印功能该怎么办呢?

接下来轮到operator(运算符重载关键字)登场了。

我们首先要注意两个重点,一是运算符,而是重载。

operator只能操作之前(语言定义的)存在过的运算符,为该运算符重新赋予新的功能,这种将运算符旧功能通过operator编写的函数,重新为它赋予新的功能就叫做重载。

现在我们接着来谈怎么实现我们的cout<<s1;

如果我们将该函数实现在类的内部,*this就会抢占第一个位置,也就是cout,但是cout实际是ostream类型的并不是Student类型,所以我们将其定义在全局。

接下来我们来一点点的解释,然后再优化一下该函数的缺点。

首先 <<左边的cout会自动的匹配到函数的第一个形参,<<右边的s1会匹配到第二个形参上去(cout << s1)。其实我们也可以将cout和s1分别看成operator<<函数的第一个实参和第二个实参。

为了减少拷贝的次数,所以使用了引用而不是简单的传值。

cout的类型是ostream的

在该函数内部的时候,out是cout的别名,out就相当于cout,我们直接使用即可,但是该类的成员变量都是private类型的,我们不能直接在类的外部进行访问,此时将我们的函数,设置为该类的友元函数即可。

 友元函数:可以访问类的内部

或者在类的内部实现三个函数,分别读取对应的三个成员变量(比较的挫不建议)

上面我们实现<<的重载的返回类型是void的,为了和我们标准的cout实现的相同,即cout<<1<<2<<endl;一次打印多个,我们将返回类型改为ostream。

完整的代码如下:

#include<iostream>
#include <string.h>

using namespace std;

class Student
{
	friend void operator<<(ostream& out, const Student& s);
public:
	Student(int age, int id, const char* name)
	{
		_age = age;
		_id = id;
		_name = new char[strlen(name) + 1];
		//const传给非const的类型是不被允许的,通过开辟新的空间拷贝的方式去实现_name
		strcpy(_name, name);
	}

	~Student()
	{
		_age = _id = 0;
		delete[] _name;
		_name = nullptr;
	}

	void print()
	{
		cout << _age << " " << _id << " " << _name << endl;
	}
private:
	int _age;
	int _id;
	char* _name;
};


ostream& operator<<(ostream& out, const Student& s)
{
	out << s._age << " " << s._id << " " << s._name << endl;
}

int main()
{
	Student s1(18, 12345, "zhangsan");
	s1.print();

	cout << s1;
	return 0;
}

运行结果:

运算符重载的用处很大,特别是对于我们的自定义类型,比如日期类的加减法,我们是无法直接对自定义的日期类使用+-的,但是可以使用运算符重载去实现日期类的+-。

我们知道,C++是兼容C的,那么C++的<<就是一个运算符的重载,当然<<在C++中也是可以作为为运算符使用的,如下:

3的二进制右移1位就是0001(十进制1) 。

在C++中会自动识别<<和>>对应的操作数的类型来决定是位运算还是运算符重载<<  >>。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山忆874

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值