重载大于有或没有朋友的运算符

use*_*396 0 c++ overloading operator-overloading

假设我有以下课程:

class Point{
private:
int x,y;

public:
int get_x() const {return x;}
int get_y() const {return y;}

Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
    x = P.get_x();
    y = P.get_y();
}
Point& operator=   (const Point& P) {
            x = P.get_x();
            y = P.get_y();

    return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {

    os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
    return os;
}


Point operator - (const Point &P){
    return Point(x-P.get_x(),y-P.get_y());
}

friend bool operator > (const Point &A, const Point &B) {
    return A.get_y()>B.get_y();
}


};
Run Code Online (Sandbox Code Playgroud)

这里我使用了好友功能。我也可以在没有朋友的情况下使用函数:

class Point{
...
bool operator > (const Point &B) const {
    return y>B.get_y();
}
 ...

};
Run Code Online (Sandbox Code Playgroud)

它们在实际实现中有何区别?同样在第二种方法中,如果没有“cont”,代码将无法编译,为什么呢?即使我将 getter 函数更改为非常量函数后,如果没有“const”,它仍然无法编译。

use*_*267 5

正如您已经注意到的,比较运算符重载可以实现为成员函数或非成员函数。

根据经验,friend您应该尽可能将它们实现为非成员非函数,因为这会增加封装性,并且允许explicit在运算符的任一侧使用(非)转换构造函数。

举例来说,您的Point类出于某种原因有一个int转换构造函数:

Point(int x);
Run Code Online (Sandbox Code Playgroud)

使用非成员比较运算符,您现在可以执行以下操作:

Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
Run Code Online (Sandbox Code Playgroud)

您似乎还对何时使用感到困惑const,再次作为比较运算符的经验法则,您应该尽可能使用const,因为逻辑上比较不涉及对对象的任何更改。

由于Point是一个非常小的类,您也可以按值来代替,因此按照从最优选到最不优选的顺序,您的选择是:

// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);

// Non-member, friend    
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);

// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;
Run Code Online (Sandbox Code Playgroud)