Function overloading
In C, every function needs its own name: area_square, area_rect, area_circle. C++ lets them share one name, as long as their parameter lists differ. This is function overloading.
Same name, different parameters
#include <iostream>
using namespace std;
int area(int side) { return side * side; }
int area(int width, int height) { return width * height; }
double area(double radius) { return 3.14159 * radius * radius; }
int main() {
cout << area(4) << endl; // one int: a square
cout << area(3, 5) << endl; // two ints: a rectangle
cout << area(2.0) << endl; // one double: a circle
return 0;
}16
15
12.5664The compiler looks at the arguments of each call and picks the version whose parameters match. It decides while compiling, so overloading costs nothing when the program runs.
Overloads may differ in the number of parameters, their types, or both.
Matching by type
#include <iostream>
#include <string>
using namespace std;
void show(int n) { cout << "int: " << n << endl; }
void show(double d) { cout << "double: " << d << endl; }
void show(char c) { cout << "char: " << c << endl; }
void show(const string& s) { cout << "string: " << s << endl; }
int main() {
show(42);
show(3.5);
show('x');
show(string("hello"));
show("a literal"); // converted to string: the only version that fits
return 0;
}int: 42
double: 3.5
char: x
string: hello
string: a literalAn exact type match wins. When there isn't one, the compiler tries standard conversions, then conversions a class provides, such as turning "a literal" into a string.
Default arguments
#include <iostream>
#include <string>
using namespace std;
void greet(const string& name, const string& greeting = "Hello", int times = 1) {
for (int i = 0; i < times; i++)
cout << greeting << ", " << name << "!" << endl;
}
int main() {
greet("Asha");
greet("Leo", "Welcome");
greet("Mei", "Hi", 2);
return 0;
}Hello, Asha!
Welcome, Leo!
Hi, Mei!
Hi, Mei!When versions differ only by leaving trailing arguments off, one function with default arguments is simpler than three overloads. Defaults go at the end of the parameter list, and a call can only leave arguments off from the right.
Calls the compiler can't decide
void f(long x) { }
void f(double x) { }
f(5); // error: call of overloaded 'f(int)' is ambiguous5 is an int. Turning it into a long and turning it into a double are equally good conversions, so neither version wins and the call doesn't compile. The fix is to say what you mean (f(5L) or f(5.0)), or to add an int overload.
The return type doesn't count
int parse(const string& s);
double parse(const string& s); // error: only the return type differsThe compiler chooses an overload from the call's arguments, and a call like parse("3") looks the same for both. Overloads need different parameters; when you need different results, give the functions different names.
Overloading in the standard library
You've used overloads since your first program. cout << 42, cout << 3.5 and cout << "text" each call a different version of <<. Writing your own << for your own types is a later step, after classes.