C++ Primer, Fifth Edition
}
Exercise 6.33: Write a recursive function to print the contents of a vector.
Exercise 6.34: What would happen if the stopping condition in factorial
were
if (val != 0)
Exercise 6.35: In the call to fact, why did we pass val - 1 rather than
val--?
6.3.3. Returning a Pointer to an Array
Because we cannot copy an array, a function cannot return an array. However, a
function can return a pointer or a reference to an array (§ 3.5.1, p. 114).
Unfortunately, the syntax used to define functions that return pointers or references to
arrays can be intimidating. Fortunately, there are ways to simplify such declarations.
The most straightforward way is to use a type alias (§ 2.5.1, p. 67):
Click here to view code image
typedef int arrT[10];  // arrT is a synonym for the type array of ten ints
using arrtT = int[10]; // equivalent declaration of arrT; see § 2.5.1 (p. 68)
arrT* func(int i);     // func returns a pointer to an array of five ints
Here arrT is a synonym for an array of ten ints. Because we cannot return an array,
we define the return type as a pointer to this type. Thus, func is a function that
takes a single int argument and returns a pointer to an array of ten ints.
Declaring a Function That Returns a Pointer to an Array
To declare func without using a type alias, we must remember that the dimension of
an array follows the name being defined:
Click here to view code image
int arr[10];          // arr is an array of ten ints
int *p1[10];          // p1 is an array of ten pointers
int (*p2)[10] = &arr; // p2 points to an array of ten ints
As with these declarations, if we want to define a function that returns a pointer to an
array, the dimension must follow the function’s name. However, a function includes a
parameter list, which also follows the name. The parameter list precedes the
dimension. Hence, the form of a function that returns a pointer to an array is:
Click here to view code image
Type (*function(parameter_list))[dimension]
www.it-ebooks.info
Convert pdf to editable ppt - C# Create PDF from PowerPoint Library to convert pptx, ppt to PDF in C#.net, ASP.NET MVC, WinForms, WPF
Online C# Tutorial for Creating PDF from Microsoft PowerPoint Presentation
convert pdf into ppt; embed pdf into powerpoint
Convert pdf to editable ppt - VB.NET Create PDF from PowerPoint Library to convert pptx, ppt to PDF in vb.net, ASP.NET MVC, WinForms, WPF
VB.NET Tutorial for Export PDF file from Microsoft Office PowerPoint
convert pdf to powerpoint online; drag and drop pdf into powerpoint
C++ Primer, Fifth Edition
As in any other array declaration, 
Type
is the type of the elements and 
dimension
is
the size of the array. The parentheses around (*
function
(
parameter_list
)) are
necessary for the same reason that they were required when we defined p2. Without
them, we would be defining a function that returns an array of pointers.
As a concrete example, the following declares func without using a type alias:
int (*func(int i))[10];
To understand this declaration, it can be helpful to think about it as follows:
• func(int) says that we can call func with an int argument.
• (*func(int)) says we can dereference the result of that call.
• (*func(int))[10] says that dereferencing the result of a call to func yields
an array of size ten.
• int (*func(int))[10] says the element type in that array is int.
Using a Trailing Return Type
Under the new standard, another way to simplify the declaration of func is by using
trailing return type. Trailing returns can be defined for any function, but are most
useful for functions with complicated return types, such as pointers (or references) to
arrays. A trailing return type follows the parameter list and is preceded by ->. To
signal that the return follows the parameter list, we use auto where the return type
ordinarily appears:
Click here to view code image
// fcn takes an int argument and returns a pointer to an array of ten ints
auto func(int i) -> int(*)[10];
Because the return type comes after the parameter list, it is easier to see that func
returns a pointer and that that pointer points to an array of ten ints.
Using 
decltype
As another alternative, if we know the array(s) to which our function can return a
pointer, we can use decltype to declare the return type. For example, the following
function returns a pointer to one of two arrays, depending on the value of its
parameter:
Click here to view code image
int odd[] = {1,3,5,7,9};
int even[] = {0,2,4,6,8};
// returns a pointer to an array of five int elements
decltype(odd) *arrPtr(int i)
www.it-ebooks.info
Online Convert PDF to Text file. Best free online PDF txt
RasterEdge PDF document conversion SDK provides reliable and effective .NET solution for Visual C# developers to convert PDF document to editable & searchable
convert pdf to powerpoint with; copying image from pdf to powerpoint
C++ Primer, Fifth Edition
{
return (i % 2) ? &odd : &even; // returns a pointer to the array
}
The return type for arrPtr uses decltype to say that the function returns a pointer
to whatever type odd has. That object is an array, so arrPtr returns a pointer to an
array of five ints. The only tricky part is that we must remember that decltype
does not automatically convert an array to its corresponding pointer type. The type
returned by decltype is an array type, to which we must add a * to indicate that
arrPtr returns a pointer.
Exercises Section 6.3.3
Exercise 6.36: Write the declaration for a function that returns a reference
to an array of ten strings, without using either a trailing return,
decltype, or a type alias.
Exercise 6.37: Write three additional declarations for the function in the
previous exercise. One should use a type alias, one should use a trailing
return, and the third should use decltype. Which form do you prefer and
why?
Exercise 6.38: Revise the arrPtr function on to return a reference to the
array.
6.4. Overloaded Functions
Functions that have the same name but different parameter lists and that appear in
the same scope are overloaded. For example, in § 6.2.4 (p. 214) we defined several
functions named print:
Click here to view code image
void print(const char *cp);
void print(const int *beg, const int *end);
void print(const int ia[], size_t size);
These functions perform the same general action but apply to different parameter
types. When we call these functions, the compiler can deduce which function we want
based on the argument type we pass:
Click here to view code image
int j[2] = {0,1};
print("Hello World");        // calls print(const char*)
print(j, end(j) - begin(j)); // calls print(const int*, size_t)
print(begin(j), end(j));     // calls print(const int*, const int*)
www.it-ebooks.info
C++ Primer, Fifth Edition
Function overloading eliminates the need to invent—and remember—names that exist
only to help the compiler figure out which function to call.
Note
The main function may 
not
be overloaded.
Defining Overloaded Functions
Consider a database application with several functions to find a record based on
name, phone number, account number, and so on. Function overloading lets us define
a collection of functions, each named lookup, that differ in terms of how they do the
search. We can call lookup passing a value of any of several types:
Click here to view code image
Record lookup(const Account&);  // find by Account
Record lookup(const Phone&);    // find by Phone
Record lookup(const Name&);     // find by Name
Account acct;
Phone phone;
Record r1 = lookup(acct);  // call version that takes an Account
Record r2 = lookup(phone); // call version that takes a Phone
Here, all three functions share the same name, yet they are three distinct functions.
The compiler uses the argument type(s) to figure out which function to call.
Overloaded functions must differ in the number or the type(s) of their parameters.
Each of the functions above takes a single parameter, but the parameters have
different types.
It is an error for two functions to differ only in terms of their return types. If the
parameter lists of two functions match but the return types differ, then the second
declaration is an error:
Click here to view code image
Record lookup(const Account&);
bool lookup(const Account&);   // error: only the return type is different
Determining Whether Two Parameter Types Differ
Two parameter lists can be identical, even if they don’t look the same:
Click here to view code image
www.it-ebooks.info
C++ Primer, Fifth Edition
// each pair declares the same function
Record lookup(const Account &acct);
Record lookup(const Account&); // parameter names are ignored
typedef Phone Telno;
Record lookup(const Phone&);
Record lookup(const Telno&); // Telno and Phone are the same type
In the first pair, the first declaration names its parameter. Parameter names are only a
documentation aid. They do not change the parameter list.
In the second pair, it looks like the types are different, but Telno is not a new
type; it is a synonym for Phone. A type alias (§ 2.5.1, p. 67) provides an alternative
name for an existing type; it does not create a new type. Therefore, two parameters
that differ only in that one uses an alias and the other uses the type to which the alias
corresponds are not different.
Overloading and const Parameters
As we saw in § 6.2.3 (p. 212), top-level const (§ 2.4.3, p. 63) has no effect on the
objects that can be passed to the function. A parameter that has a top-level const is
indistinguishable from one without a top-level const:
Click here to view code image
Record lookup(Phone);
Record lookup(const Phone);   // redeclares Record lookup(Phone)
Record lookup(Phone*);
Record lookup(Phone* const);  // redeclares Record lookup(Phone*)
In these declarations, the second declaration declares the same function as the first.
On the other hand, we can overload based on whether the parameter is a reference
(or pointer) to the const or nonconst version of a given type; such consts are
low-level:
Click here to view code image
// functions taking const and nonconst references or pointers have different
parameters
// declarations for four independent, overloaded functions
Record lookup(Account&);       // function that takes a reference to
Account
Record lookup(const Account&); // new function that takes a const
reference
www.it-ebooks.info
C++ Primer, Fifth Edition
Record lookup(Account*);       // new function, takes a pointer to
Account
Record lookup(const Account*); // new function, takes a pointer to const
In these cases, the compiler can use the constness of the argument to distinguish
which function to call. Because there is no conversion (§ 4.11.2, p. 162) 
from
const,
we can pass a const object (or a pointer to const) only to the version with a
const parameter. Because there is a conversion 
to
const, we can call either
function on a nonconst object or a pointer to nonconst. However, as we’ll see in §
6.6.1 (p. 246), the compiler will prefer the nonconst versions when we pass a
nonconst object or pointer to nonconst.
const_cast and Overloading
In § 4.11.3 (p. 163) we noted that const_casts are most useful in the context of
overloaded functions. As one example, recall our shorterString function from §
6.3.2 (p. 224):
Click here to view code image
// return a reference to the shorter of two strings
const string &shorterString(const string &s1, const string
&s2)
{
return s1.size() <= s2.size() ? s1 : s2;
}
Advice: When Not to Overload a Function Name
Although overloading lets us avoid having to invent (and remember) names
for common operations, we should only overload operations that actually do
similar things. There are some cases where providing different function
names adds information that makes the program easier to understand.
Consider a set of functions that move the cursor on a Screen.
Click here to view code image
Screen& moveHome();
Screen& moveAbs(int, int);
Screen& moveRel(int, int, string direction);
It might at first seem better to overload this set of functions under the name
move:
Click here to view code image
Screen& move();
Screen& move(int, int);
Screen& move(int, int, string direction);
www.it-ebooks.info
C++ Primer, Fifth Edition
However, by overloading these functions, we’ve lost information that was
inherent in the function names. Although cursor movement is a general
operation shared by all these functions, the specific nature of that movement
is unique to each of these functions. moveHome, for example, represents a
special instance of cursor movement. Whether to overload these functions
depends on which of these two calls is easier to understand:
Click here to view code image
// which is easier to understand?
myScreen.moveHome(); // we think this one!
myScreen.move();
This function takes and returns references to const string. We can call the
function on a pair of nonconst string arguments, but we’ll get a reference to a
const string as the result. We might want to have a version of shorterString
that, when given nonconst arguments, would yield a plain reference. We can write
this version of our function using a const_cast:
Click here to view code image
string &shorterString(string &s1, string &s2)
{
auto &r = shorterString(const_cast<const string&>(s1),
const_cast<const string&>(s2));
return const_cast<string&>(r);
}
This version calls the const version of shorterString by casting its arguments to
references to const. That function returns a reference to a const string, which
we know is bound to one of our original, nonconst arguments. Therefore, we know it
is safe to cast that string back to a plain string& in the return.
Calling an Overloaded Function
Once we have defined a set of overloaded functions, we need to be able to call them
with appropriate arguments. Function matching (also known as overload
resolution) is the process by which a particular function call is associated with a
specific function from a set of overloaded functions. The compiler determines which
function to call by comparing the arguments in the call with the parameters offered by
each function in the overload set.
In many—probably most—cases, it is straightforward for a programmer to
determine whether a particular call is legal and, if so, which function will be called.
Often the functions in the overload set differ in terms of the number of arguments, or
the types of the arguments are unrelated. In such cases, it is easy to determine which
function is called. Determining which function is called when the overloaded functions
have the same number of parameters and those parameters are related by
www.it-ebooks.info
C++ Primer, Fifth Edition
conversions (§ 4.11, p. 159) can be less obvious. We’ll look at how the compiler
resolves calls involving conversions in § 6.6 (p. 242).
For now, what’s important to realize is that for any given call to an overloaded
function, there are three possible outcomes:
• The compiler finds exactly one function that is a best match for the actual
arguments and generates code to call that function.
• There is no function with parameters that match the arguments in the call, in
which case the compiler issues an error message that there was no match.
• There is more than one function that matches and none of the matches is
clearly best. This case is also an error; it is an ambiguous call.
Exercises Section 6.4
Exercise 6.39: Explain the effect of the second declaration in each one of
the following sets of declarations. Indicate which, if any, are illegal.
(a) int calc(int, int);
int calc(const int, const int);
(b) int get();
double get();
(c) int *reset(int *);
double *reset(double *);
6.4.1. Overloading and Scope
Warning
Ordinarily, it is a bad idea to declare a function locally. However, to explain
how scope interacts with overloading, we will violate this practice and use
local function declarations.
Programmers new to C++ are often confused about the interaction between scope
and overloading. However, overloading has no special properties with respect to
scope: As usual, if we declare a name in an inner scope, that name 
hides
uses of that
name declared in an outer scope. Names do not overload across scopes:
Click here to view code image
string read();
void print(const string &);
www.it-ebooks.info
C++ Primer, Fifth Edition
void print(double);   // overloads the print function
void fooBar(int ival)
{
bool read = false; // new scope: hides the outer declaration of read
string s = read(); // error: read is a bool variable, not a function
// bad practice: usually it's a bad idea to declare functions at local scope
void print(int);  // new scope: hides previous instances of print
print("Value: "); // error: print(const string &) is hidden
print(ival);      // ok: print(int) is visible
print(3.14);      // ok: calls print(int); print(doubleis hidden
}
Most readers will not be surprised that the call to read is in error. When the compiler
processes the call to read, it finds the local definition of read. That name is a bool
variable, and we cannot call a bool. Hence, the call is illegal.
Exactly the same process is used to resolve the calls to print. The declaration of
print(int) in fooBar hides the earlier declarations of print. It is as if there is
only one print function available: the one that takes a single int parameter.
When we call print, the compiler first looks for a declaration of that name. It finds
the local declaration for print that takes an int. Once a name is found, the compiler
ignores uses of that name in any outer scope. Instead, the compiler assumes that the
declaration it found is the one for the name we are using. What remains is to see if
the use of the name is valid.
Note
In C++, name lookup happens before type checking.
The first call passes a string literal, but the only declaration for print that is in
scope has a parameter that is an int. A string literal cannot be converted to an int,
so this call is an error. The print(const string&) function, which would have
matched this call, is hidden and is not considered.
When we call print passing a double, the process is repeated. The compiler finds
the local definition of print(int). The double argument can be converted to an
int, so the call is legal.
Had we declared print(int) in the same scope as the other print functions,
then it would be another overloaded version of print. In that case, these calls would
be resolved differently, because the compiler will see all three functions:
Click here to view code image
void print(const string &);
void print(double); // overloads the print function
www.it-ebooks.info
C++ Primer, Fifth Edition
void print(int);    // another overloaded instance
void fooBar2(int ival)
{
print("Value: "); // calls print(const string &)
print(ival);      // calls print(int)
print(3.14);      // calls print(double)
}
6.5. Features for Specialized Uses
In this section we’ll cover three function-related features that are useful in many, but
not all, programs: default arguments, inline and constexpr functions, and some
facilities that are often used during debugging.
6.5.1. Default Arguments
Some functions have parameters that are given a particular value in most, but not all,
calls. In such cases, we can declare that common value as a default argument for
the function. Functions with default arguments can be called with or without that
argument.
For example, we might use a string to represent the contents of a window. By
default, we might want the window to have a particular height, width, and background
character. However, we might also want to allow users to pass values other than the
defaults. To accommodate both default and specified values we would declare our
function to define the window as follows:
Click here to view code image
typedef string::size_type sz;  // typedef see § 2.5.1 (p. 67)
string screen(sz ht = 24, sz wid = 80, char backgrnd = ' ');
Here we’ve provided a default for each parameter. A default argument is specified as
an initializer for a parameter in the parameter list. We may define defaults for one or
more parameters. However, if a parameter has a default argument, all the parameters
that follow it must also have default arguments.
Calling Functions with Default Arguments
If we want to use the default argument, we omit that argument when we call the
function. Because screen provides defaults for all of its parameters, we can call
screen with zero, one, two, or three arguments:
Click here to view code image
string window;
window = screen();  // equivalent to screen(24,80,' ')
www.it-ebooks.info
Documents you may be interested
Documents you may be interested