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;
	}

执行结果与上面相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++运算符重载是一种特性,允许我们重新定义已有的运算符的行为,使其适用于自定义的数据型。差集运算符(-)也可以进行重载。 差集运算符用于计算两个集合之间的差异,即从一个集合中去除另一个集合中存在的元素。在C++中,我们可以通过重载差集运算符来实现集合的差集操作。 下面是一个示例代码,演示了如何重载差集运算符: ```cpp #include <iostream> #include <set> class Set { private: std::set<int> elements; public: Set() {} Set(std::initializer_list<int> initList) { for (int element : initList) { elements.insert(element); } } Set operator-(const Set& other) const { Set difference; for (int element : elements) { if (other.elements.find(element) == other.elements.end()) { difference.elements.insert(element); } } return difference; } void print() const { for (int element : elements) { std::cout << element << " "; } std::cout << std::endl; } }; int main() { Set set1 = {1, 2, 3, 4, 5}; Set set2 = {3, 4, 5, 6, 7}; Set difference = set1 - set2; difference.print(); // 输出: 1 2 return 0; } ``` 在上面的示例中,我们定义了一个名为Set的,表示一个集合。通过重载差集运算符(operator-),我们可以使用减号操作符来计算两个Set对象之间的差集。在重载函数中,我们遍历第一个集合的元素,并检查它们是否存在于第二个集合中。如果不存在,则将其添加到差集中。 相关问题: 1. 什么是运算符重载? 2. 如何重载其他运算符? 3. 运算符重载有什么注意事项

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值