C++基础(十九)运算符重载注意事项

类的运算符重载是C++一个非常基础也很重要的语法,很多文章都有说到,但是,很多文章里面的写法其实都是不对的,或者说不完美的。

一般的运算符,可以有两种重载方式:

1、作为类的成员函数;

2、作为类的友元函数。

作为成员函数,因为有隐藏的this指针,所以二元运算符只需要一个参数即可;作为友元,二元运算符则需要两个参数。

当然,有一些运算符的重载必须用友元,例如标准输入输出>>、<<等。

请看下面一段代码:

#include <iostream>

class Test
{
public:
	Test(int i) : m_iValue(i) { std::cout << "构造函数\n"; }
	Test(const Test& t) { m_iValue = t.m_iValue; std::cout << "copy构造函数\n"; }

	bool operator<(const Test& t)
	{
		return this->m_iValue < t.m_iValue;
	}

	friend std::ostream& operator<<(std::ostream& os, const Test& t)
	{
		std::cout << "value = " << t.m_iValue;
		return os;
	}

private:
	int m_iValue{ 0 };
};

template<typename T>
T Max(T left, T right)
{
	return left < right ? right : left;
}

int main()
{
	using namespace std;

	Test t1(20), t2(18);
	cout << "----------------------------\n";
	cout << Max<Test>(t1, t2) << "\n";

	system("pause");
	return 0;
}

执行结果如下(vs2019):

这段代码很简单,定义了一个Test类,重载了"<"运算符,用的是类的成员函数的方法;还重载了标准输出运算符<<,打印m_iValue的数字;

接着定义了一个很简单的模板函数Max,返回两个对象的较大一个。

主函数里,定义了Test的两个对象t1和t2,调用Max模板函数,打印较大的一个。

从执行结果可以看出来,Max的设计很不好,因为参数是值传递的,返回值也是一个临时对象,会调用拷贝构造函数,如果类很大,开销会很大。

Max函数其实是返回两个较大对象中的一个,说白了完全可以返回对象本身,而函数内部,并不会对参数进行任何修改,所以完全可以将Max模板函数改成如下形式,提高效率:

template<typename T>
const T& Max(const T& left, const T& right)
{
	return left < right ? right : left;
}

但是!!!会发现编译不过:

从错误提示可以看出来,似乎和const有关系。问题出在哪里呢?

其实问题出在"<"的重载上:bool operator<(const Test& t);

仔细分析,“const Test& t”其实是<的右操作数,那左操作数呢?当然是“*this”,如何限定这个"*this"也是const,很简单,在重载“<”函数的后面加上const修饰,完整代码如下:

#include <iostream>

class Test
{
public:
	Test(int i) : m_iValue(i) { std::cout << "构造函数\n"; }
	Test(const Test& t) { m_iValue = t.m_iValue; std::cout << "copy构造函数\n"; }

	bool operator<(const Test& t) const  //注意,这里函数最后的const是修饰这个函数的,表示内部不会修改任何成员变量
	{
		return this->m_iValue < t.m_iValue;
	}

	friend std::ostream& operator<<(std::ostream& os, const Test& t)
	{
		std::cout << "value = " << t.m_iValue;
		return os;
	}

private:
	int m_iValue{ 0 };
};

template<typename T>
const T& Max(const T& left, const T& right)
{
	return left < right ? right : left;
}

int main()
{
	using namespace std;

	Test t1(20), t2(18);
	cout << "----------------------------\n";
	cout << Max<Test>(t1, t2) << "\n";

	system("pause");
	return 0;
}

执行结果如下:

少了三次拷贝构造。

除此之外,加上引用后,Max还能用于那些不能拷贝构造的类对象上!

如果采用类的成员函数方式重载运算符,如果运算符不会修改成员变量,一定要用const修改运算符重载函数!

否则,不仅仅是这个Max函数,很多东西都不能用。比如,set容器、map容器的key、标准库函数std::max等等,C++的类设计,不那么容易。

当然,上面的例子中,如果改成友元函数,就不会涉及这个问题:

	friend bool operator<(const Test& left, const Test& right)
	{
		return left.m_iValue < right.m_iValue;
	}

执行结果与上面相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值