将运算符重载为友元函数

作者:jicanmeng

时间:2014年11月17日


When the operator does not modify its operands, the best way to overload the operator is via friend function. learncpp.com上面列举了四个例子:

  1. 算术运算符(arithmetic operators)重载
  2. 输入输出运算符(I/O operators)重载
  3. 比较运算符(comparison operators)重载
  4. 一元运算符(unary operators)重载

1. 算术运算符(arithmetic operators)重载

#include <iostream>
using namespace std;

class Cents
{
private:
    int m_nCents;
public:
    Cents(int nCents){
        m_nCents = nCents;
    }

    //Overload Cents + Cents
    friend Cents operator+(const Cents &c1, const Cents &c2);
    // Overload cCents + int
    friend Cents operator+(const Cents &cCents, int nCents);

    int GetCents(){
        return m_nCents;
    }
};

Cents operator+(const Cents &c1, const Cents &c2)
{
    return Cents(c1.m_nCents + c2.m_nCents);
}

Cents operator+(const Cents &c1, int nCents)
{
    return Cents(c1.m_nCents + nCents);
}

int main()
{
    Cents cCents1(6);
    Cents cCents2(8);
    Cents cCentsSum1 = cCents1 + cCents2;
    Cents cCentsSum2 = cCents1 + 7;
    cout << "sum1 have " << cCentsSum1.GetCents() << " cents" << endl;
    cout << "sum2 have " << cCentsSum2.GetCents() << " cents" <<endl;

    return 0;
}

2. 输入输出运算符(I/O operators)重载

#include <iostream>
using namespace std;

class Point
{
private:
    double m_dX, m_dY, m_dZ;

public:
    Point(double dX=0.0, double dY=0.0, double dZ=0.0){
        m_dX = dX;
        m_dY = dY;
        m_dZ = dZ;
    }

    friend ostream& operator<< (ostream &out, Point &cPoint);
    friend istream& operator>> (istream &in, Point &cPoint);

    double GetX() { return m_dX; }
    double GetY() { return m_dY; }
    double GetZ() { return m_dZ; }
};

ostream& operator<< (ostream &out, Point &cPoint)
{
    // Since operator<< is a friend of the Point class, we can access
    // Point's members directly.
    out << "(" << cPoint.m_dX << ", " <<
        cPoint.m_dY << ", " <<
        cPoint.m_dZ << ")";
    return out;
}

istream& operator>> (istream &in, Point &cPoint)
{
    in >> cPoint.m_dX;
    in >> cPoint.m_dY;
    in >> cPoint.m_dZ;
    return in;
}

int main()
{
    Point cPoint1(2.0, 3.0, 4.0);
    Point cPoint2(6.0, 7.0, 8.0);
    cout << cPoint1 << " " << cPoint2 << endl;

    cout << "Enter a point: " << endl;
    Point cPoint;
    cin >> cPoint;
    cout << "You entered: " << cPoint << endl;

    return 0;
}

3. 比较运算符(comparison operators)重载

#include <iostream>
using namespace std;

class Point
{
private:
    double m_dX, m_dY, m_dZ;

public:
    Point(double dX=0.0, double dY=0.0, double dZ=0.0){
        m_dX = dX;
        m_dY = dY;
        m_dZ = dZ;
    }

    friend bool operator== (Point &cP1, Point &cP2);
    friend bool operator!= (Point &cP1, Point &cP2);

    double GetX() { return m_dX; }
    double GetY() { return m_dY; }
    double GetZ() { return m_dZ; }
};

bool operator== (Point &cP1, Point &cP2)
{
    return (cP1.m_dX == cP2.m_dX &&
            cP1.m_dY == cP2.m_dY &&
            cP1.m_dZ == cP2.m_dZ);
}

bool operator!= (Point &cP1, Point &cP2)
{
    return !(cP1 == cP2);
}

int main()
{
    Point cPoint1(2.0, 3.0, 4.0);
    Point cPoint2(6.0, 7.0, 8.0);

    if(cPoint1 == cPoint2){
        cout << "cPoint == cPoint2" << endl;
    }else{
        cout << "cPoint != cPoint2" << endl;
    }

    return 0;
}

4. 一元运算符(unary operators)重载

#include <iostream>
using namespace std;

class Cents
{
private:
    int m_nCents;
public:
    Cents(int nCents = 0){
        m_nCents = nCents;
    }

    // Overload -cCents
    friend Cents operator-(const Cents &cCents);

    // Return true if use default constructor
    friend bool operator! (const Cents &cCents);

    int GetCents(){
        return m_nCents;
    }
};

// note: this function is not a member function!
Cents operator-(const Cents &cCents)
{
    return Cents(-cCents.m_nCents);
}

// Return true if use default constructor
bool operator! (const Cents &cCents)
{
    return (cCents.m_nCents == 0);
}

int main()
{
    Cents cCents1(6);
    Cents cCentsSum = -cCents1;
    cout << "I have " << cCentsSum.GetCents() << " cents" << endl;

    Cents cCents2; // use default contructor to set to m_nCents = 0
    if(!cCents2){
        cout << "cCents2 was set use default constructor." << endl;
    }else{
        cout << "cCents2 was set use reload constructor." << endl;
    }

    return 0;
}

参考资料

  1. The C++ Tutorial:
    http://www.learncpp.com/