2019独角兽企业重金招聘Python工程师标准>>>
#include <iostream>
using namespace std;
class point
{
public:
point():x(0.0),y(0.0){}
point(double a, double b){ x=a; y=b; }
double getx(){ return x;}
double gety(){ return y;}
void setx(double val){ x = val;}
void sety(double val){ y = val;}
point operator+(point &p)
{
point sum(x+p.getx(),y+p.gety());
return sum;
}
friend ostream& operator<< (ostream &out,point &p)
{
out<<"("<<p.x<<","<<p.y<<")";
return out;
}
private:
double x,y;
};
int main()
{
point a,b,c;
a.setx(1.2);
a.sety(2.1);
b.setx(2.5);
b.sety(3.2);
c = a+b;
cout<<c<<endl;
return 0;
}
上面的小例子是来自coursera课程中的《C++ for C programmers》的ppt,自己输入一遍运行发现老是出错,出错的原因是“<<”操作符重载的问题。原来类的成员函数在重载一元操作符时,不能在显式声明参数,从在二元操作符时,只能显式声明一个形参,这个形参表示右操作数,左操作数由引用参数提供。所以如果要重载"<<"的话,必须使用friend。
操作符重载
C++语言提供的标准运算符可以在类中重新定义的机制——运算符重载。
C++中可被重载的操作符:+ - * / % ^ & | ~
! = < > += -= *= /= %=
^= &= | = << >> >>= <<= == !=
<= >= && || ++ -- [ ] () ->
->* , new new[] delete delete[ ]
重载操作符函数时参数要求:
§ 对于一元操作符函数:
l 重载为成员函数时,不能再显式声明参数。
§ 对于二元操作符函数:
l 重载为成员函数时,只能显式声明一个形参,这个形参表示右操作数,左操作数由引用参数提供。
重载操作符要注意的问题:
§ 对操作符的重载不改变操作符的优先级和结合性。
§ 重载不改变操作符的语法。
§ 如果一个内建操作符是一元的,那么所有对它的重载仍是一元的。
§ 如果一个内建操作符是二元的,那么所有对它的重载仍是二元的。
§ 被重载的操作符要么是一个类的成员函数,要么在他的参数表中包含一个类对象。
Friend 函数
§ 类的私有成员只能被该类的成员函数和该类的friend函数访问;类的保护成员只能被该类的或其派生类的成员函数和该类的friend函数访问。
§ 为了使函数f成为类C的friend,在类C的声明里使用关键字friend对f进行声明。
§ 该声明的作用是赋予f访问C的私有和保护成员的权力,因为f不是成员函数,该声明可以放在C中的private、protected或public的任意部分。
§ Friend函数不仅可以是顶层函数,也可以是另一个类中的成员函数。
§ 一个函数可以同时被多个类声明为“friend”,这样就可以引用多个类中的私有数据。
§ 不仅可以将一个函数声明为一个类的friend, 也可以将一个类声明为另一个类的friend。
§ 声明friend类的一般形式是:
friend类名;
例如可以在上例中将整个Time类声明为Date类的friend。这样time中的所有函数都可以访问Date中的所有成员。
§ Friend的关系是单向的,不是双向的,如果声明了A是B的friend,不等于B是A的friend.
§ Friend的关系不能传递。
§ friend函数不是类的成员函数,却可以访问该类的私有和保护成员,从严格意义上来说,这不符合面向对象原则。
§ 因此friend函数是存在争议的,且容易被误用。
§ 建议仅在重载操作符时使用friend函数。