Skip to content

Commit f6c86e7

Browse files
mikeblomeColin Robertson
authored andcommitted
Mb ref qualifiers (MicrosoftDocs#562)
* in progress updates for ref-qualified overloads * updates to two topics on functions * new date
1 parent 7662c99 commit f6c86e7

File tree

2 files changed

+120
-69
lines changed

2 files changed

+120
-69
lines changed

docs/cpp/function-overloading.md

Lines changed: 115 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Function Overloading | Microsoft Docs"
33
ms.custom: ""
4-
ms.date: "11/04/2016"
4+
ms.date: "1/25/2018"
55
ms.reviewer: ""
66
ms.suite: ""
77
ms.technology: ["cpp-language"]
@@ -17,9 +17,11 @@ manager: "ghogen"
1717
ms.workload: ["cplusplus"]
1818
---
1919
# Function Overloading
20-
C++ allows specification of more than one function of the same name in the same scope. These are called overloaded functions and are described in detail in Overloading. Overloaded functions enable programmers to supply different semantics for a function, depending on the types and number of arguments.
20+
C++ allows specification of more than one function of the same name in the same scope. These are called *overloaded* functions. Overloaded functions enable you to supply different semantics for a function, depending on the types and number of arguments.
2121

22-
For example, a **print** function that takes a string (or **char \***) argument performs very different tasks than one that takes an argument of type **double**. Overloading permits uniform naming and prevents programmers from having to invent names such as `print_sz` or `print_d`. The following table shows what parts of a function declaration C++ uses to differentiate between groups of functions with the same name in the same scope.
22+
For example, a **print** function that takes a **std::string** argument might perform very different tasks than one that takes an argument of type **double**. Overloading saves you from having to use names such as `print_string` or `print_double`. At compile time, the compiler chooses which overload to use based on the type of arguments passed in by the caller. If you call **print(42.0)** then the **void print(double d)** function will be invoked. If you call **print("hello world")** then the **void print(std::string)** overload will be invoked.
23+
24+
You can overload both member functions and non-member functions. The following table shows what parts of a function declaration C++ uses to differentiate between groups of functions with the same name in the same scope.
2325

2426
### Overloading Considerations
2527

@@ -31,9 +33,8 @@ C++ allows specification of more than one function of the same name in the same
3133
|Presence or absence of ellipsis|Yes|
3234
|Use of `typedef` names|No|
3335
|Unspecified array bounds|No|
34-
|**const** or `volatile` (see below)|Yes|
35-
36-
Although functions can be distinguished on the basis of return type, they cannot be overloaded on this basis. `Const` or `volatile` are only used as a basis for overloading if they are used in a class to apply to the **this** pointer for the class, not the function's return type. In other words, overloading applies only if the **const** or `volatile` keyword follows the function's argument list in the declaration.
36+
|**const** or `volatile`|Yes, when applied to entire function|
37+
|[ref-qualifier](#ref-qualifier)|Yes|
3738

3839
## Example
3940
The following example illustrates how overloading can be used.
@@ -43,68 +44,71 @@ C++ allows specification of more than one function of the same name in the same
4344
// compile with: /EHsc
4445
#include <iostream>
4546
#include <math.h>
46-
47+
#include <string>
48+
4749
// Prototype three print functions.
48-
int print( char *s ); // Print a string.
49-
int print( double dvalue ); // Print a double.
50-
int print( double dvalue, int prec ); // Print a double with a
51-
// given precision.
52-
using namespace std;
53-
int main( int argc, char *argv[] )
54-
{
55-
const double d = 893094.2987;
56-
if( argc < 2 )
57-
{
58-
// These calls to print invoke print( char *s ).
59-
print( "This program requires one argument." );
60-
print( "The argument specifies the number of" );
61-
print( "digits precision for the second number" );
62-
print( "printed." );
63-
exit(0);
64-
}
65-
66-
// Invoke print( double dvalue ).
67-
print( d );
68-
69-
// Invoke print( double dvalue, int prec ).
70-
print( d, atoi( argv[1] ) );
71-
}
72-
50+
int print(std::string s); // Print a string.
51+
int print(double dvalue); // Print a double.
52+
int print(double dvalue, int prec); // Print a double with a
53+
// given precision.
54+
using namespace std;
55+
int main(int argc, char *argv[])
56+
{
57+
const double d = 893094.2987;
58+
if (argc < 2)
59+
{
60+
// These calls to print invoke print( char *s ).
61+
print("This program requires one argument.");
62+
print("The argument specifies the number of");
63+
print("digits precision for the second number");
64+
print("printed.");
65+
exit(0);
66+
}
67+
68+
// Invoke print( double dvalue ).
69+
print(d);
70+
71+
// Invoke print( double dvalue, int prec ).
72+
print(d, atoi(argv[1]));
73+
}
74+
7375
// Print a string.
74-
int print( char *s )
75-
{
76-
cout << s << endl;
77-
return cout.good();
78-
}
79-
76+
int print(string s)
77+
{
78+
cout << s << endl;
79+
return cout.good();
80+
}
81+
8082
// Print a double in default precision.
81-
int print( double dvalue )
82-
{
83-
cout << dvalue << endl;
84-
return cout.good();
85-
}
86-
87-
// Print a double in specified precision.
83+
int print(double dvalue)
84+
{
85+
cout << dvalue << endl;
86+
return cout.good();
87+
}
88+
89+
// Print a double in specified precision.
8890
// Positive numbers for precision indicate how many digits
8991
// precision after the decimal point to show. Negative
9092
// numbers for precision indicate where to round the number
9193
// to the left of the decimal point.
92-
int print( double dvalue, int prec )
93-
{
94-
// Use table-lookup for rounding/truncation.
95-
static const double rgPow10[] = {
96-
10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1, 10E0,
97-
10E1, 10E2, 10E3, 10E4, 10E5, 10E6
98-
};
99-
const int iPowZero = 6;
100-
// If precision out of range, just print the number.
101-
if( prec < -6 || prec > 7 )
102-
return print( dvalue );
103-
// Scale, truncate, then rescale.
104-
dvalue = floor( dvalue / rgPow10[iPowZero - prec] ) *
105-
rgPow10[iPowZero - prec];
106-
cout << dvalue << endl;
107-
return cout.good();
94+
int print(double dvalue, int prec)
95+
{
96+
// Use table-lookup for rounding/truncation.
97+
static const double rgPow10[] = {
98+
10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1,
99+
10E0, 10E1, 10E2, 10E3, 10E4, 10E5, 10E6 };
100+
const int iPowZero = 6;
101+
102+
// If precision out of range, just print the number.
103+
if (prec < -6 || prec > 7)
104+
{
105+
return print(dvalue);
106+
}
107+
// Scale, truncate, then rescale.
108+
dvalue = floor(dvalue / rgPow10[iPowZero - prec]) *
109+
rgPow10[iPowZero - prec];
110+
cout << dvalue << endl;
111+
return cout.good();
108112
}
109113
```
110114

@@ -391,8 +395,47 @@ obj.name
391395
```
392396

393397
The left operand of the `->*` and `.*` (pointer to member) operators are treated the same way as the `.` and `->` (member-selection) operators with respect to argument matching.
394-
395-
## Restrictions
398+
399+
## <a name="ref-qualifiers"></a> Ref-qualifiers on member functions
400+
Ref qualifiers make it possible to overload a member function on the basis of whether the object pointed to by `this` is an rvalue or an lvalue. This feature can be used to avoid unnecessary copy operations in scenarios where you choose not to provide pointer access to the data. For example, assume class **C** initializes some data in its constructor, and returns a copy of that data in member function **get_data()**. If an object of type **C** is an rvalue that is about to be destroyed, then the compiler will choose the **get_data() &&** overload, which moves the data rather than copy it.
401+
402+
```cpp
403+
#include <iostream>
404+
#include <vector>
405+
406+
using namespace std;
407+
408+
class C
409+
{
410+
411+
public:
412+
C() {/*expensive initialization*/}
413+
vector<unsigned> get_data() &
414+
{
415+
cout << "lvalue\n";
416+
return _data;
417+
}
418+
vector<unsigned> get_data() &&
419+
{
420+
cout << "rvalue\n";
421+
return std::move(_data);
422+
}
423+
424+
private:
425+
vector<unsigned> _data;
426+
};
427+
428+
int main()
429+
{
430+
C c;
431+
auto v = c.get_data(); // get a copy. prints "lvalue".
432+
auto v2 = C().get_data(); // get the original. prints "rvalue"
433+
return 0;
434+
}
435+
436+
```
437+
438+
## Restrictions on overloading
396439
Several restrictions govern an acceptable set of overloaded functions:
397440

398441
- Any two functions in a set of overloaded functions must have different argument lists.
@@ -435,10 +478,13 @@ obj.name
435478
void Print( char szToPrint[][9][42] );
436479
```
437480
438-
## Declaration matching
481+
## Overloading, overriding, and hiding
482+
439483
Any two function declarations of the same name in the same scope can refer to the same function, or to two discrete functions that are overloaded. If the argument lists of the declarations contain arguments of equivalent types (as described in the previous section), the function declarations refer to the same function. Otherwise, they refer to two different functions that are selected using overloading.
440484
441-
Class scope is strictly observed; therefore, a function declared in a base class is not in the same scope as a function declared in a derived class. If a function in a derived class is declared with the same name as a function in the base class, the derived-class function hides the base-class function instead of causing overloading.
485+
Class scope is strictly observed; therefore, a function declared in a base class is not in the same scope as a function declared in a derived class. If a function in a derived class is declared with the same name as a virtual function in the base class, the derived-class function *overrides* the base-class function. For more information, see [Virtual Functions](../cpp/virtual-functions.md).
486+
487+
If the base class function is not declared as 'virtual', then the derived class function is said to *hide* it. Both overriding and hiding are distinct from overloading.
442488
443489
Block scope is strictly observed; therefore, a function declared in file scope is not in the same scope as a function declared locally. If a locally declared function has the same name as a function declared in file scope, the locally declared function hides the file-scoped function instead of causing overloading. For example:
444490
@@ -518,7 +564,10 @@ double Account::Deposit( double dAmount, char *szPassword )
518564
else
519565
return 0.0;
520566
}
521-
```
567+
```
568+
569+
570+
522571
523572
## See Also
524573
[Functions (C++)](../cpp/functions-cpp.md)

docs/cpp/functions-cpp.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: "Functions (C++) | Microsoft Docs"
33
ms.custom: ""
4-
ms.date: "11/04/2016"
4+
ms.date: "01/25/2018"
55
ms.reviewer: ""
66
ms.suite: ""
77
ms.technology: ["cpp-language"]
@@ -40,6 +40,8 @@ int main()
4040
There is no practical limit to function length, but good design aims for functions that perform a single well-defined task. Complex algorithms should be broken up into easy-to-understand simpler functions whenever possible.
4141

4242
Functions that are defined at class scope are called member functions. In C++, unlike other languages, a function can also be defined at namespace scope (including the implicit global namespace). Such functions are called *free functions* or *non-member functions*; they are used extensively in the Standard Library.
43+
44+
Functions may be *overloaded*, which means different versions of a function may share the same name if they differ by the number and/or type of formal parameters. For more information, see [Function Overloading](../cpp/function-overloading.md).
4345

4446
## Parts of a function declaration
4547
A minimal function *declaration* consists of the return type, function name, and parameter list (which may be empty), along with optional keywords that provide additional instructions to the compiler. The following example is a function declaration:
@@ -117,7 +119,7 @@ int sum(int a, int b)
117119
118120
7. (member functions only) `static` applied to a member function means that the function is not associated with any object instances of the class.
119121
120-
8. (Non-static member functions only) The ref-qualifier, which specifies to the compiler which overload of a function to choose when the implicit object parameter (*this) is an rvalue reference vs. an lvalue reference.
122+
8. (Non-static member functions only) The ref-qualifier, which specifies to the compiler which overload of a function to choose when the implicit object parameter (*this) is an rvalue reference vs. an lvalue reference. For more information, see [Function Overloading](function-overloading.md#ref-qualifiers).
121123
122124
The following figure shows the parts of a function definition. The shaded area is the function body.
123125
@@ -363,7 +365,7 @@ int main()
363365
}
364366
```
365367

366-
4. In addition to using the return value itself, you can "return" values by defining any number of parameters to use pass-by-reference so that the function can modify or initialize the values of objects that the caller provides. For more information, see [Reference-Type Function Arguments](reference-type-function-arguments.md).
368+
4. In addition to using the return value itself, you can "return" values by defining any number of parameters to use pass-by-reference so that the function can modify or initialize the values of objects that the caller provides. For more information, see [Reference-Type Function Arguments](reference-type-function-arguments.md).
367369

368370
## Function pointers
369371
C++ supports function pointers in the same manner as the C language. However a more type-safe alternative is usually to use a function object.

0 commit comments

Comments
 (0)