类的操作符重载及友元函数

若想要定义的类成员能够符合人类逻辑使用已有的语言内置操作符,可以大幅提高编程效率和代码可读性


其一般语法为:

class test{
public:
       ......
       typename operator name(){
              ......
       }
       .......
};

 举一实例:

class Box{
private:
	int l,b,h;
public:
	//读取参数的构造函数,可用Box object=Box(A,B,C);或Box object(A,B,C);构造对象
	Box(int A,int B,int C){
		l=A;b=B;h=C;
	}

	long long calVolume(){
		return l*b*h;
	}

	//返回Box类对象的引用
	//引用比指针好,引用确定后是不能重新指向别的对象的,同时也不能指向空值
	//每个对象都有一个指向自己的this指针
	//类成员与结构体相似,可以通过指针this->func()来代替*p.func()
	Box & orerator <(Box & box){  //这里用引用参数是为了方便比较完谁的体积大后对返回对象进行操作,
									//否则最后的返回值是个copy,在其上的操作并不能修改到box
		if(this->calVolume() <= box.calVolume()){
			return box;
		}
		else{
			return *this;  //返回指针的函数return地址,返回变量copy或引用的函数return变量
		}
	}

	~Box(){}
};

其中,Box& operator <(){};重载了<运算符,使其可以比较两个Box类实例的大小,并返回较大的那个实例的引用。

这里还要提到类成员里的this预定义指针,指向成员本身。


对于一般的操作符,可以用类成员函数直接重载,但有一些不行,下面举两个例子

① * 操作符:

若直接在类成员函数里重载,如下

void operator *(int num){
       cout<<l*num<<" "<<b*num<<" "<<h*num<<endl;
}

则当编译 box*2(Box box(1,2,3))时,隐式调用了operator *(box,2),由于box为类实例,在类成员函数内类实例本身默认为第一个参数,其它参数是从函数的第二个形参开始赋值,所以上述代码相当于调用了box.operator*(2),会输出12。

但若是编译器遇到2*box呢?编译器遇到*号会试图调用int型的乘操作,但右操作数为Box类成员,所以无解,而且此式也不符合Box类重载的乘运算,因为此式相当于隐式调用了operator*(2,box),其参数位置颠倒,会遇到错误。

所以现在解决问题的关键在于要定义一个函数,其第一个参数为int型,第二个参数为Box类。显然这个函数不能定义在类内部,因为类成员函数的第一个参数默认为类实例本身,所以这个函数要定义在类外。但是一个类外的函数无法访问类中的变量,所以我们需要的是一个,不在类内却能访问类成员的函数。

具体实现方法如下,在类内部定义一个友元函数:

friend int operator*(int num,Box& box){
       cout<<box.l<<" "<<box.b<<" "<<box.h<<endl;
}


本质上,这个函数应该只在类内部声明函数名和返回类型,以及用friend关键字来表明其是友元函数,其函数体应该在类外定义,但简写也无妨。


② << 操作符:

<<是stream操作符,当使用os << variable时,编译器隐式调用了operator<<(ostream& os,typename variable),由此可见,operator<<()地第一参数为其左操作符,一个ostream,第二个参数为要放入这个输出流的内容。

若要对Box类实现<<操作,使其能够简单地进行cout<<box;操作,则需要为其重载<<操作符。显然,重载函数不能为类成员函数,因为第一个参数不是类实例,所以我们要用到友元函数。如下

//友元函数是外部函数,用于处理第一参数不是类成员的情况,因为一般类成员函数是默认对象为第一参数的	
//类成员在友元函数内就是普通参数,可以把友元函数理解成给一个函数访问类成员内部变量的权限
//stream<<object 等于 operator <<(stream,object),所以重载<<时要遵循其格式,其第一参数为流对象,要用友元
//能用引用尽量用引用
friend ostream & operator <<(ostream& os,Box& B){  //这里ostream& os的引用为<<指向的变量,比如cout
	os<<B.l<<" "<<B.b<<" "<<B.h;
	return os;
这里最后返回ostream os变量的引用,是为了让其能够实现cout<<box<<other things操作,此式相当于(cout<<box)<<other things。



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值