将运算符重载为成员函数

作者:jicanmeng

时间:2014年11月17日


For operators that do modify their operands, we typically overload the operator using a member function of the class.

Overloading operators using a member function is very similar to overloading operators using a friend function. When overloading an operator using a member function:

  1. The leftmost operand of the overloaded operator must be an object of the class type.
  2. The leftmost operand becomes the implicit *this parameter. All other operands become function parameters.

Most operators can actually be overloaded either way, however there are a few exception cases:

  1. If the leftmost operand is not a member of the class type, such as when overloading operator+(int, YourClass), or operator<<(ostream&, YourClass), the operator must be overloaded as a friend.
  2. The assignment (=), subscript ([]), call (()), and member selection (->) operators must be overloaded as member functions.

learncpp.com上面列举了几个例子:

  1. 算术运算符(arithmetic operators)重载
  2. 自增运算符和自减运算符(increment and decrement operators)重载
  3. 下标运算符(subscript operator)重载
  4. 括号运算符(parenthesis operator)重载
  5. 强制转换运算符(typecasts operators)重载
  6. 一元运算符(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
    Cents operator+(int nCents);

    int GetCents(){
        return m_nCents;
    }
};

//note: this function is not a member function!
Cents operator+(const Cents &c1, const Cents &c2)
{
    //use the Cents constructor and operator+(int, int)
    return Cents(c1.m_nCents + c2.m_nCents);
}

Cents Cents::operator+(int nCents)
{
    return Cents(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. 自增运算符和自减运算符(increment and decrement operators)重载

#include <iostream>
using namespace std;

class Digit
{
private:
    int m_nDigit;
public:
    Digit(int nDigit=0)
    {
        m_nDigit = nDigit;
    }

    Digit& operator++(); // prefix
    Digit& operator--(); // prefix

    Digit operator++(int); // postfix
    Digit operator--(int); // postfix

    int GetDigit() const { return m_nDigit; }
};

Digit& Digit::operator++()
{
    // If our number is already at 9, wrap around to 0
    if (m_nDigit == 9)
        m_nDigit = 0;
    // otherwise just increment to next number
    else
        ++m_nDigit;

    return *this;
}

Digit& Digit::operator--()
{
    // If our number is already at 0, wrap around to 9
    if (m_nDigit == 0)
        m_nDigit = 9;
    // otherwise just decrement to next number
    else
        --m_nDigit;

    return *this;
}

Digit Digit::operator++(int)
{
    // Create a temporary variable with our current digit
    Digit cResult(m_nDigit);

    // Use prefix operator to increment this digit
    ++(*this);             // apply operator

    // return temporary result
    return cResult;       // return saved state
}

Digit Digit::operator--(int)
{
    // Create a temporary variable with our current digit
    Digit cResult(m_nDigit);

    // Use prefix operator to increment this digit
    --(*this);             // apply operator

    // return temporary result
    return cResult;       // return saved state
}

int main()
{
    Digit cDigit1(5), cDigit2(5), digit1, digit2;
	digit1 = ++cDigit1; // calls Digit::operator++();
    digit2 = cDigit2++; // calls Digit::operator++(int);

    cout << "digit1 is " << digit1.GetDigit() << endl;
	cout << "digit2 is " << digit2.GetDigit() << endl;

    return 0;
}

3. 下标运算符(subscript operator)重载

#include <iostream>
#include <cassert> // for assert()
using namespace std;

class IntList
{
private:
    int m_anList[10];

public:
    int& operator[] (const int nIndex);
};

int& IntList::operator[] (const int nIndex)
{
    assert(nIndex >= 0 && nIndex < 10);
    return m_anList[nIndex];
}

int main()
{
    IntList cMyList;
    cMyList[2] = 3; 			// set a value
    cout << cMyList[2] << endl; // get a value

    return 0;
}

4. 括号运算符(parenthesis operator)重载

#include <iostream>
#include <cassert> // for assert()
using namespace std;

class Matrix
{
private:
    double adData[4][4];
public:
    Matrix(){
        // Set all elements of the matrix to 0.0
        for (int nCol=0; nCol<4; nCol++)
            for (int nRow=0; nRow<4; nRow++)
                adData[nRow][nCol] = 0.0;
    }

    double& operator()(const int nCol, const int nRow);
    void operator()();
};

double& Matrix::operator()(const int nCol, const int nRow)
{
    assert(nCol >= 0 && nCol < 4);
    assert(nRow >= 0 && nRow < 4);

    return adData[nRow][nCol];
}

void Matrix::operator()()
{
    // reset all elements of the matrix to 0.0
    for (int nCol=0; nCol<4; nCol++)
        for (int nRow=0; nRow<4; nRow++)
            adData[nRow][nCol] = 0.0;
}

int main()
{
    Matrix cMatrix;
    cMatrix(1, 2) = 4.5;
    cout << cMatrix(1, 2) << endl;
    cMatrix(); // erase cMatrix
    cout << cMatrix(1, 2) << endl;
    return 0;
}

5. 强制转换运算符(typecasts operators)重载

#include <iostream>
using namespace std;

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

    // Overloaded int cast
    operator int() { return m_nCents; }

    int GetCents() { return m_nCents; }
    void SetCents(int nCents) { m_nCents = nCents; }
};

class Dollars
{
private:
    int m_nDollars;
public:
    Dollars(int nDollars=0)
    {
        m_nDollars = nDollars;
    }

     // Allow us to convert Dollars into Cents
     operator Cents() { return Cents(m_nDollars * 100); }
};

void PrintInt(int nValue)
{
    cout << nValue;
}

void PrintCents(Cents cCents)
{
//    cout << cCents.GetCents();		//use this line of code or next line
    PrintInt(cCents);
}

int main()
{
    Cents cCents(7);
    PrintInt(cCents); // cCents will be cast tot a int
    cout << endl;

    int nCents = static_cast<int>(cCents);
    cout << "using explicitly cast: nCents is " << nCents << endl;

    Dollars cDollars(9);
    PrintCents(cDollars); // cDollars will be cast to a Cents
    cout << endl;

    return 0;
}

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

#include <iostream>
using namespace std;

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

    int GetCents(){
        return m_nCents;
    }
};

Cents Cents::operator-()
{
    return Cents(-m_nCents);
}

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

    return 0;
}

参考资料

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