股票

C++操作符重载、友邻函数

1,操作符重载

跟函数重载意思一样,就是把操作符重新定义一遍,让它能适应特别的操作,比如类的加减乘除啊、输入输出什么的,好处是在使用的时候更坚定,一个+、-写出来就可以让两个类进行操作,看起来也比较符合习惯。

C++++重要规则:只要没有歧义,函数能唯一解释,你想怎样编程就怎样编程,包括重载、省略、简化!

声明是这样子:

Time operator+(const Time & t) const;

在class.h里面public部分声明,Time是类名称,operator+表明操作符,+是操作符,后面跟函数就一模一样了。

然后是函数定义:

Time Time::operator+(const Time & t) const

{

Time sum;

sum.x = x+t.x;

sum.y = y+t.y;

return sum;

}

函数里面如何定义跟普通函数重载没区别的。

调用:

Time total, add1, add2;

total = add1.operator+(add2);

这样子看出来了吧,operator+是类函数名字,operator+()就是add1这个类的类函数,参数是add2。

现在看操作符重载的优势:.operator可以省略掉!!

total = add1+add2;

这样看起来多么直观,跟普通的常数加减一样,但是执行的时候调用operator+()这个类函数。

根据加法的交换律:

total = add2+add1;

但是这时候operator()变成了add2的类函数,虽然结果与原来一样。

2,友元函数

先看例子

声明:Time operator*(double mult) const;

定义:

Time Time::operator*(double mult)const

{

Time result;

result.x = x*mult;

result.y = y*mult;

return result;

}

这还是操作符*重载,和+、-这种没区别。

调用的时候:

Time result, mult1; double m;

result = mult1.operator*(m);

把.operator省略掉:

result = mult1*m;

我们知道乘法也有交换律:result = m*mult1;

但是现在问题来了,我们知道,这样写是因为吧.operator省略了,现在把它补回去,发现不行了,因为m不是Time类,只是个double类型,没有类函数。为了解决这个问题,C++++引入了友元函数。

friend Time operator*(double m, const Time & t);

这是声明部分,在类的public中声明,但是前面加了friend,表明这不是个类函数,不是类函数有什么好处呢,待会儿解答。

定义:

Time operator*(double m, const Time & t)

{

Time result;

result.x = m*t.x;

result.y = m*t.y;

return result;

}

跟类函数的区别是,函数名operator*之前没有类名Time::,表明友元函数不是类函数。但是因为它是在类中声明的,所以友元函数可以使用类中的private对象:比如t.x、t.y。这是别的函数不具备的功能,正是友元函数特殊之处。

这时候再来看

result = m*mult1;

正常调用应该是result = operator*(m, mult1); 但是现在我们是操作符重载,整这么复杂,当然要有些优势啦,所以可以写成:

result = m*mult1;

这样,碰到操作符*的情况

result = mult1*m;翻译成:result = mult1.operator*(m);

result = m*mult1;翻译成:result = operator*(m, mult1);

之所以这样子,是因为*是二元操作符,默认把左右两边的参数都当成自己的参数。

也许有人会问,可不可以定义一个这样的类函数:

Time operator*(double m, const Time & t) const;

把m, 和t都当参数调用,然后调用的时候:

result = m*mult1;

这个没法解释,因为m, mult1都是参数,operator*()这个类函数的类对象没了。并且编译的时候,编译器会提示你operator*是个二元操作符,而你传入了三个参数,以为它默认类对象是第一个参数。

而友元函数没有这问题,因为它不是类函数,所以就没有类对象,所以不会多出一个参数。

3,<<、>>重载

通过对<<重载,可以直接输出类中的内容,cout << mult1; 比较直观,使用的也是友元函数。

friend std::ostream & operator<<(std::ostream & os, const Time & t);

为什么不用类函数?因为使用了类函数的话,调用的时候:

mult1.operator<<(cout);

省略掉.operator就变成了:mult1 << cout;

看起来很奇怪,使用友元函数,第一个参数用std::ostream, 第二个参数用类,这样就看起来比较正常了。

为什么返回类型是 std::ostream & ? 这是为了兼容:

cout << mult1 << mult2 << mult3;

因为根据cout 的调用顺序从左向右,每次返回的都是cout本身,而不是副本。

>>重载基本一样,需要注意的是>>类型是输入std::istream。

4,类的自动转换

定义类

class Stonewt

{

private:

int stone;

double pds_left;

double pounds;

public:

Stonewt(double lbs);// #1

Stonewt(int stn, double lbs);// #2

Stonewt();// #3

Stonewt operator+(const Time & t) const;

Stonewt operator-(const Time & t) const;

Stonewt operator*(const Time & t) const;

};

我们知道,类的初始化可以用:

Stonewt stone1=Stonewt(5); // #1

Stonewt stone2(5); // #1

Stonewt stone3=Stonewt(5, 2); // #2

Stonewt stone4(5, 2); // #2

Stonewt stone5; // #3

但是可不可以这样呢?

Stonewt stone6=5;

或者这样:

Stonewt stone7;

stone7 = 5;

答案是可以的!

这个有什么用呢?

看以下调用:

Stonewt result;

result = stone1+stone2; // 直接调用 stone1.operator+(stone2);

result = stone1+5; // stone1.operator+(5),由于operator+()函数的参数是Stonewt类型,这里会直接调用Stonewt(5),以符合函数类型。

再看一个:

result = 5+stone1;

这个要怎么解释?先把5转换为Stonewt(5)再使用operator+()???但是,编译器不是这么想的。因为类函数中有operator+这个二元操作符,而这里5和stone1刚好是两个参数,所以它会把直接带入,然后发现其需要的两个参数都是Stonewt类型,而这里一个int一个Stonewt类型,不符合要求。

这里需要友元函数进行解释:

friend Stonewt operator*(int m, const Stonewt & s) {return s*m};

friend Stonewt operator+(int m, const Stonewt & s) {return s+m};

friend Stonewt operator-(int m, const Stonewt & s) {return Stonewt(m)-t};

打赏
原文链接:,转发请注明来源!

发表评论