The i < n test stops the loop after n characters have been copied. The second part of the test, the expression str[i], is the code for the character about to be copied. If the loop reaches the null character, the code is 0, and the loop terminates. The final while loop terminates the string with the null character and then sets the rest of the allocated space, if any, to null characters.

Another approach for setting the size of the new string is to set n to the smaller of the passed value and the string length:

int len = strlen(str);

n = (n < len) ? n : len;    // the lesser of n and len

char * p = new char[n+1];

This ensures that new doesn’t allocate more space than what’s needed to hold the string. That can be useful if you make a call such as left("Hi!", 32767). The first approach copies the "Hi!" into an array of 32767 characters, setting all but the first 3 characters to the null character. The second approach copies "Hi!" into an array of 4 characters. But by adding another function call (strlen()), it increases the program size, slows the process, and requires that you remember to include the cstring (or string.h) header file. C programmers have tended to opt for faster running, more compact code and leave a greater burden on the programmer to use functions correctly. However, the C++ tradition places greater weight on reliability. After all, a slower program that works correctly is better than a fast program that works incorrectly. If the time taken to call strlen() turns out to be a problem, you can let left() determine the lesser of n and the string length directly. For example, the following loop quits when m reaches n or the end of the string, whichever comes first:

int m = 0;

while (m <= n && str[m] != '\0')

      m++;

char * p = new char[m+1]:

// use m instead of n in rest of code

Remember, the expression str[m] != '\0' evaluates to true when str[m] is not the null character and to false when it is the null character. Because nonzero values are converted to true in an && expression and zero is converted to false, the while test also can be written this way:

while (m<=n && str[m])

Function Overloading

Function polymorphism is a neat C++ addition to C’s capabilities. Whereas default arguments let you call the same function by using varying numbers of arguments, function polymorphism, also called function overloading, lets you use multiple functions sharing the same name. The word polymorphism means having many forms, so function polymorphism lets a function have many forms. Similarly, the expression function overloading means you can attach more than one function to the same name, thus overloading the name. Both expressions boil down to the same thing, but we’ll usually use the expression function overloading—it sounds harder working. You can use function overloading to design a family of functions that do essentially the same thing but using different argument lists.

Overloaded functions are analogous to verbs having more than one meaning. For example, Miss Piggy can root at the ball park for the home team, and she can root in soil for truffles. The context (one hopes) tells you which meaning of root is intended in each case. Similarly, C++ uses the context to decide which version of an overloaded function is intended.

The key to function overloading is a function’s argument list, also called the function signature. If two functions use the same number and types of arguments in the same order, they have the same signature; the variable names don’t matter. C++ enables you to define two functions by the same name, provided that the functions have different signatures. The signature can differ in the number of arguments or in the type of arguments, or both. 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 you then use a print() function, the compiler matches your use to the prototype that has the same signature:

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

For example, print("Pancakes", 15) uses a string and an integer as arguments, and it matches Prototype #1.

When you use overloaded functions, you need to be sure you use the proper argument types in the function call. For example, consider the following statements:

unsigned int year = 3210;

print(year, 6);           // ambiguous call

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги