C++小细节8-重载运算

04/23/2020

C++重载运算

  • 关键字operator和其后要定义的运算符号
  • 包含返回类型,参数列表以及函数体
  • 参数列表重载完之后应该与原先的一样
    • 一元运算符:一个参数
    • 二元运算符:两个参数,例如加号左侧运算对象属于参数列表的第一个,右侧属于第二个。
    • (+,-,*,&)既是一元又是二元
    • 不允许有默认实参,除了函数调用运算符operator()
  • 如果运算符函数是成员函数,它的第一个(左侧)运算对象绑定到隐式的this指针上,所以参数列表会少一个。
  • 不能被重载的运算符:作用域运算符(:😃,成员访问运算符(.),三元条件运算符(?😃,指向成员的指针(.*)
data1 + data2;
operator+(data1,data2); //相互之间等价,本质函数调用

比较重要的重载运算符

输入输出运算符

- 输入运算符**必须**处理输入可能的情况,而输出不需要。
- 注意参数列表中输入类型的引用和返回类型的引用。
- 通常在类中,声明友元函数比较好理解,**不建议声明**成类成员函数,看例子:
- 输入输出是二元运算符,只有两个形参。

例子1: 输出重载符中的成员函数与非成员函数

class ClassType
{
public:
	ostream& operator<<(ostream& os) //类成员函数,隐藏了this指针
	{
		os << name << age;
		return os;
	}
	friend ostream& operator<<(ostream& os,const ClassType& item);
private:
	
	std::string name;
	int age;
};

//强调ostream对象不能被拷贝,所以用引用,返回ostream& 原因是因为可以继续连续输出别的信息;
ostream& operator<<(ostream& os,const ClassType& item) //友元函数
{
	os << item.name << item.age;
	return os;
}

//main function
ClassType data;
data << cout; 			//这边会难以理解,因为顺序是反的。
data.operator<<(cout);	//和上面一个意思


cout << data; //调用友元函数的输出
cout << data << "\n";//如果返回值不是ostream&, 后续的换行符是无法输出的。

例子2: 输入重载符

istream& operator>>(istream& is, ClassType& item) //友元函数
{
	is >> item.name >> item.age;
	if(!is) //如果输入流失败
	{
		item = ClassType(); //默认构造函数被使用。
	}
	return is;
}
- 输出与输入有哪些不同?
	- 检查流状态
	- 输出重载的对象可以是const作为形参列表,而输入不可以。
istream& operator>>(istream &is, ClassType& item);//输入有可能失败,例如类型不相等,检查输入流状态
ostream& operator<<(ostream &os, const ClassType& item);//输出不需要
  • 算术和关系运算符
    • 加号(+),注意返回值是没有引用的
    • 一组相等和不相等运算符,返回bool类型
    • 关系运算符,大于小于。。。
    • 赋值运算符,返回值必然是左侧对象的引用,也一定是类成员函数
    • 复合赋值运算符 +=, 一定是类成员函数,返回左侧运算对象的引用
  • 下标运算符
    • 以中括号(“[]”)为标志作为声明,代表返回数组首个元素的地址
    • 下表运算符必须是成员函数
class StrVec
{
public:
	StrVec(std::size_t size):element(new string(size)){} 
	//版本1
	std::string& operator[](std::size_t n) //下标越界问题
	{
		return element[n]; //返回一个string的引用
	}
	//版本二 类的常量成员并返回常量引用,返回值无法被改变
	const std::string& operator[](std::size_t n)const;
private:
	std::string* element; //指向数组首元素的指针
};
StrVec(10);
temp[2] = "zero"; //左值引用
  • 递增和递减运算符
    • 不要求必须是类的成员函数,但是它们改变的正好是所操作对象的状态,所以建议将其设定为成员函数
    • 前置:应该返回递增或递减后对象的引用
    • 后置:返回对象的原值
    • 一元运算符,只有一个形参
class BOperator
{
public:
	BOperator& operator++(); //前置运算符
	BOperator& operator--();

	BOperator operator++(); //后置运算符
	BOperator operator--();
};
  • 成员访问运算符
    • 解引用运算符(*)和箭头运算符(->)
    • 箭头运算符必须作为类的成员函数,但是解引用通常也是。
class BOperator
{
public:
	std::string& opeartor*() const
	{
		auto p = check(curr,"dereference past end");
		return (*p)[curr]; 
	}
	std::string& operator->()const
	{
		return &this->operator*(); //委托给解引用运算符
	}

};
  • 函数调用运算符1必须是成员函数
    • 格式:operator()
    • 应用:C++标准库定义的函数对象。
//函数调用运算符必须使成员函数,所以必须有类或者结构体。
//多个不同版本的调用运算符,有着不同的参数数量或类型
struct absInt //结构体
{
	int operator()(int val)const{ //不要忘记小括号!operator()
		return val < 0 ? -val:val;
	}
	double operator()(double val)const{ //可以使用数据成员
		os << point <<endl;
		return ++val;
	}
	ostream &os = cout;
	float point = 3.0;
};

int i = -42;
absInt absObj;
int ui = absObj(i);//重载函数调用 

标准库function类型

声明函数

#include <functional> //函数库

function<int(int,int)> f1 = add;//函数指针
function<int(int,int)> f2 = add();//函数对象类的对象
function<int(int,int)> f3 = [](int i,int j){return i*j;};

重载的函数与function

对于重载函数,只能使用lambda或者函数指针,指定初哪一个是需要的

类型转换运算符2

  • 它是类的一种特殊成员函数,负责将一个类类型的值转换成其他类型。
  • 一般形式: operator type() const;
  • 不允许转换成数组或者函数类型,但允许转换成指针(包括数组指针和函数指针)或者引用类型。
  • 没有返回类型,也没有形参,必须是类成员函数,形参列表是空
  • 通常是const的成员函数

例子:

class SmallInt
{
public:
  SmallInt(int i = 0):val(i){}
  SmallInt& operator=(const SmallInt& a){cout << "assign\n";}
  operator int()const{return val;}
private:
  int val = 0;

};
int main()
{
  SmallInt obj;
  obj = 4; //调用赋值运算符opeartor=,int 4转换为类类型SmallInt
  cout << obj + 4; //调用类型转换运算符,SmallInt类类型Obj转换为Int
  return 0;
}

  1. C++ primer 第五版 14.8 ↩︎

  2. C++ primer 第五版 14.9 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值