#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函數。