Function Overloading

Overloading allows you to create multiple functions of the same name with different implementations.

  • two or more methods in one class have the same method name but different in # or types of parameters

We can do this for regular functions, or do it for Constructor overloading.

Overloading vs Overriding

Example (taken from Wikipedia)

#include <iostream>
 
int Volume(int s) { // Volume of a cube.
 return s * s * s;
}
 
double Volume(double r, int h) { // Volume of a cylinder.
 return 3.1415926 * r * r * static_cast<double>(h);
}
 
long Volume(long l, int b, int h) { // Volume of a cuboid.
 return l * b * h;
}
 
int main() {
 std::cout << Volume(10);
 std::cout << Volume(2.5, 8);
 std::cout << Volume(100l, 75, 15);
}

We can also overload based on different types of arguments:

bool negate(bool b) {
	return !b;
}
int negate(int x) {
	return -x;
}

You CANNOT overload based on return type

You cannot overload based solely on return type. The overloaded function must differ based on different number of arguments and the type of arguments.

Why? Because the return type does not participate in the function signature, which is used by the compiler to differentiate between overloaded functions.

What happens if you try overloading solely based on return type?

The return types can be different for different overloads, but you need to make sure that at least either the number or type of arguments is different. Else, you will get a compilation error.

Operating Overloading

Seen in CS247.

To perform an operator overload, we define a function with the name “operator” concatenated with the operator symbol.

operator+, operator>>, operator!, operator==,

The number of args must match the arity of the operator. eg:

    • : binary operator - 2 args
  • ! : unary operator - 1 arg

Example

// defined inside the class Rational
Rational& operator=(const Rational& rhs) {
	num = rhs.num;
	denom = rhs.denom;
	return *this;
}

Certain Operator overloads need to be inside the class

There are some operator overloads that MUST be defined as methods (as opposed to standalolone functions). These are:

  • operator=
  • operator[]
  • operator->
  • operator()
  • operator T where T is a type

Remember that when you implement an operator overload as a method of a class, this is the LHS, and the RHS is the argument passed to the operator.

Overloadable / Non-Overloadable Operators

https://www.tutorialspoint.com/cplusplus/cpp_overloading.htm

Note

Operator << and >> are usually defined as standalone functions (outside of the class). Because cin and cout appears on the lhs.

istream& operator>>(istream& in, Rational& r) {
	in >> r.num;
	in >> r.denom;
	return in;
}
Commutativity of Operators (not a thing)

If we want to support r + 5, we implement the following operator

class Rational {
	...
	Rational operator+(int rhs) {
		...
	}
}

However, what about 5 + r? It doesn’t work, because order of arguments matters.

unless we had the following:

Rational operator+(int lhs, const Rational& rhs) {
	return rhs + lhs;
}
  • Note that this is a standalone function, defined outside of the class.

I remember that in Python, we have methods like __add__() and __radd__()

If you want to combine overloading and overriding, consider the Visitor Pattern.