OOP C9 Overloaded operators

Overloading Operators allows user-defined types(class) to act like built-in types. It is another way to make a function call.

Overloaded operators

  • Unary operators that can be overloaded:

    ! ++ --

    operator new operator new[]
    operator delete operator delete[]

  • Binary operators that can not be overloaded:

    + - * / % ^ & | ~ << >>

    = < > += -= *= /= %= ^= &= |= >>= <<=

    == != <= >= && ||

    , ->* -> () []

  • Operators that can’t be overloaded:

    • 4 important: . .* :: ?:
    • sizeof typeid
    • static_cast dynamic_cast const_cast reinterpret_cast

Restrictions of overloading

  1. Only existing operators can be overloaded—— No creating new operators !
  2. Operators must be overloaded on a class or enumeration type
  3. Overloaded operators must preserve number of operands
  4. Overloaded operators must preserve precedence.

Overloaded Operator: A function

keyword : operator , a prefix to name.

Function Type

The function could be a member function or a global / free function.

As member functions

1
2
3
4
5
6
7
8
9
10
class Integer { 
public:
Integer(int n = 0 ) : i(n) {}
const Integer operator+(const Integer& n) const{
return Integer(i + n.i);
}
...
private:
int i;
};
  • Implicit first argument

  • No type conversion performed on receiver

    1
    2
    3
    z = x + y //OK, x.operator+(y)
    z = x + 3 //OK
    z = 3 + y //Error!
  • Developer Must have access to class definition

  • Members have full access to all data in class

As a member function, the object itself already provides one argument. Therefore,

  • For binary operators (+, -, * .etc), member functions require one argument.
  • For unary operators (unary -, ! .etc), member functions require no arguments.

As global functions

1
2
3
const Integer operator+(const Integer& rhs, const Integer& lhs);
Integer x, y;
x + y; //operator+(x,y);
  • Explicit first argument

  • Type conversions performed on both arguments

    1
    2
    3
    4
    z = x + y; 
    z = x + 3;
    z = 3 + y;
    z = 3 + 7;
  • Developer does not need special access to classes

  • Can be made a friend function

    1
    2
    3
    4
    5
    6
    7
    8
    class Integer { 
    friend const Integer operator+ (const Integer& lhs, const Integer& rhs);
    ...
    }

    const Integer operator+(const Integer& lhs, const Integer& rhs){
    return Integer(lhs.i + rhs.i );
    }
  • For binary operators (+, -, * .etc), member functions require two argument.

  • For unary operators (unary -, ! .etc), member functions require one arguments.

If you don’t have access to private data members, then the global function must use the public interface (e.g. accessors)

Members vs. Free Functions

  • Unary operators should be member functions.
  • = () [] -> ->* MUST BE MEMBER FUNCTION !
  • All other binary operators should be global functions.

Argument and Return values

Argument Passing

  • read-only: pass it in as a const reference.(except built-ins)
  • don’t change the class: make member functions const, e.g boolean, +, - .etc
  • argument that might change: pass as reference.

Return values

Select the return type depending on the expected meaning of the operator.

  • Logical operators should return bool or int.
  • Const object so the result cannot be modified as an left value.

How to write?

prototypes

1
2
3
const T operatorX(const T& l, const T& r); //+-*/%^&|~ –
bool operatorX(const T& l, const T& r); //! && || < <= == >= > –
E& T::operator[](int index);//[]

postfix and prefix, ++ and –

Postfix forms take an argument, which is not used actually. It is only for distinguishing, complier will pass a 0.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Integer { 
public: ...
const Integer& operator++(); //prefix++
const Integer operator++(int); //postfix++
const Integer& operator--(); //prefix--
const Integer operator--(int); //postfix--
...
};

const Integer& Integer::operator++() {
*this += 1; // increment
return *this;
}
const Integer Integer::operator++(int){
Integer old(*this ); // fetch
++(*this); // increment,call prefix++
return old;
}

prefix++ is more efficient for postfix++ call prefix++. Compliers will do the optimization automatically today.

1
2
3
4
5
Integer x(5);
++x; // calls x.operator++();
x++; // calls x.operator++(0);
--x; // calls x.operator--();
x--; // calls x.operator--(0);

Relational operators

1
2
3
4
5
6
7
8
9
10
class Integer { 
public:
...
bool operator==(const Integer& rhs ) const;
bool operator!=(const Integer& rhs ) const;
bool operator<(const Integer& rhs ) const;
bool operator>(const Integer& rhs ) const;
bool operator<=(const Integer& rhs ) const;
bool operator>=(const Integer& rhs ) const;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
bool Integer::operator==(const Integer& rhs ) const { 		return i == rhs.i;
}
bool Integer::operator!=(const Integer& rhs ) const {
return !(*this == rhs);
//== is overloaded alreay, implement != through ==
}
bool Integer::operator<(const Integer& rhs ) const {
return i < rhs.i;
}
//implement >,>=,<= through <
bool Integer::operator>( const Integer& rhs ) const {
return rhs < *this;
}
bool Integer::operator<=( const Integer& rhs ) const {
return !(rhs < *this);
}
bool Integer::operator>=( const Integer& rhs ) const {
return !(*this < rhs);
}

Operator []

  • Must be a member function, single argument.
  • t should return a reference rather a pointer.

stream extractor >>

1
2
3
4
5
6
7
8
istream& operator>>(istream& is, T& obj) { 
// specific code to read obj
return is;
}
ostream& operator<<(ostream& os, const T& obj) {
// specific code to write obj
return os;
}

Therefore,

1
2
3
4
cin >> a >> b >> c; 
((cin >> a) >> b) >> c; //equivalent
cout << a << b << c;
((cout << a) << b) << c;//equivalent

In this way, we can creating our own manipulators like

1
2
3
ostream& manip(ostream& out) { ...
return out;
}

for instance,

1
2
3
4
5
ostream& tab ( ostream& out ) { 
return out << '\t';
}
cout << "Hello" << tab << "World!" << endl;
//Hello World!

OOP C9 Overloaded operators
http://example.com/2023/05/16/OOP-9/
Author
Tekhne Chen
Posted on
May 16, 2023
Licensed under