c + + start from scratch - function overloading

1. Concept of function overloading

Using function overloading to create functions enables users to use multiple functions with the same name. They do different jobs and use different parameter lists, but the function names are the same.
Overloaded functions are like verbs with multiple meanings. The key to overloading a function is the parameter list of the function - also known as the function signature. If the number and type of parameters of two functions are the same, and the order of parameters is the same, their characteristics are the same, and the variable name is irrelevant. For example, you can define a set of print() functions with the following prototypes:

void print(const char *str, int width); // #1
void print(double d, int width); // #2
void print(long l, int width);// #3
void print(int i, int width); // #4
void print(const char* str); // #5

When using the print() function, the compiler will use the prototype with corresponding characteristics according to the usage:

print("Pancakes", 15); // use #1
print("Syrup");        // use #5
print(1999.0, 10);     // use #2
print(1999, 12);  	   // use #4
print(1999L, 15);      // use #3 

When the input parameter type does not match any overloaded function, c + + will try to force the match using standard type conversion. For example:

unsigned int year = 2000;
print(year, 5);

Because the overloaded function print() does not have the first parameter of type unsigned, C + + attempts type casting. If the print() function has only #2 (no #3 and #4) types, then #2 will be used directly. However, the first parameters of #2, 3 and 4 of print() are all numbers, so c + + can't force conversion and will refuse to execute the code.

2. Precautions

  1. When checking the function signature, the compiler will treat the type reference and the type itself as the same signature:
double cube(double x);
double cube(double &x);

When the parameter x is input, both prototypes match each other.

  1. When matching functions, distinguish between const and non const variables:
void dribble(char * bits);
void dribble(const char *cbits);
void drip(char* bits);

const char p1[10] = "wang";
char p2[10] = "wang";
dribble(p1);
dribble(p2);
drip(p1); no match

Note that the dribble() function can enter const and non const parameters, but the drill () function cannot enter const parameters. Because const value cannot be assigned to non const value.

  1. Signature is the key to function overloading, not function type:
long gronk(int n, float m);
double gronk(int n,float m);

The above two functions are mutually exclusive. They are not overloaded functions, but the function names are the same. c + + will not know how to use them.

3. Overload reference parameters

Class design and STL often use reference parameters, so it is important to know the overloading of different reference types. Please see the following three prototypes:

void sink(double & r1); // Matches the modifiable lvalue parameter
void sank(const double & r2); // Matches the modifiable lvalue parameter, const lvalue parameter and rvalue parameter
void sunk(double && r3); // Match right value

Note that the parameters that match r1 and r3 match r2. What happens if you overload a function that uses these three parameters? The answer is that the most matching version will be called:

void stove(double & r1);
void stove(const double &r2);
void stove(double && r3);

double x = 55.5;
const double y = 32.0;
stove(x); // calls stove(double &)
stove(y); // calls stove(const double &)
stove(x+y); // calls stove(double&&)

In the above program, if the function stop (double & &) is not defined, stop (x + y) will call stop (const double &).

4. When to use overloading

One principle should be adhered to: function overloading should only be used when functions basically perform the same task but use different forms of data.

Supplementary content - left and right values (see reference for details) here)

1. Concepts of left and right values
In C + +, lvalue and rvalue are relatively basic concepts. Although they are rarely used, they become very important after C++11. They are the basis for understanding new semantics such as move/forward.
The two concepts of left value and right value are inherited from C. left value refers to variables that can appear both on the left and on the right of the equal sign; right value refers to variables that can only appear on the right of the equal sign.

int a; // a is the left value
a = 3; // 3 is the right value

Lvalues are addressable variables with persistence;
The right value is generally a non addressable constant or an unnamed temporary object created during the evaluation of an expression. It is transient.
One of the main differences between left value and right value is that the left value can be modified, while the right value cannot.
2. Lvalue reference and rvalue reference
Lvalue reference: refers to an object;
Right value reference: it refers to the reference that must be bound to the right value. In C++11, the right value reference can realize "mobile semantics" and obtain the right value reference through & &.

int x = 6; // x is the left value and 6 is the right value
int &y = x; // Lvalue reference, y reference x
int &z1 = x * 6; // Error, x*6 is an R-value
const int &z2 =  x * 6; // Correct, you can bind a const reference to an rvalue
int &&z3 = x * 6; // Correct, right value reference
int &&z4 = x; // Error, x is an lvalue

R-value reference and related mobile semantics are one of the most powerful features introduced in C++11 standard. Unnecessary replication can be avoided and program performance can be improved through std::move().

Keywords: C++

Added by maest on Sat, 04 Dec 2021 06:53:55 +0200