The premise behind any function in any language is simple: encapsulate a process under one name. Then, by calling that name (i.e., invoking the function), you can repeat that sequence of steps with ease. You’ve already seen this in action when you use the functions defined in C++, like cin.get()
or the close()
function used with files. In this chapter you’ll learn how to define and call your own functions.
The syntax for defining a function is simple and consistent, but there are many permutations as to what a function can do. For starters, you’ll create a simple function, one that takes no arguments and returns no values. Then you’ll begin writing functions that take required arguments, and then those that take optional arguments. After that, you’ll define functions that actually return a value, like the result of a computation. From these rudimentary concepts, the chapter delves into the more sophisticated notion of overloading functions. The chapter concludes with a lesson on variable scope: understanding where variables exist. As you go through the chapter, you’ll also see a few other tidbits about related topics, like inline functions, recursive functions, and other variable designations.
There are two steps to defining a function in C++. First you establish the function’s syntax, using a function prototype. The prototype indicates the function’s name, what type and number of arguments it takes, if any, and what kind of value, if any, it returns. The prototype does not include the actual content of the function itself. The prototype is necessary so that the compiler can confirm that a function is being used correctly when it is called (the compiler will see the prototype, then the invocation of the function).
The syntax for the prototype is
typeReturned functionName (arguments);
If the function returns no value, its typeReturned will be void
. All of the functions defined in this chapter will only ever return a simple numeric type, like int
or float
. In the next two chapters, you’ll learn about, and have functions return, more complex types. (As an aside, it makes no difference whether you have a space between the function’s name and its opening parentheses; in this book we will sometimes add a space to make the result more legible.)
The rules for naming functions are the same as those for naming variables: you use alphanumeric characters plus the underscore. Remember that function names are case-sensitive in C++, so you should stick to a consistent capitalization strategy. Also, as with variables, you cannot use an existing keyword for your functions (like int
or break
, and so on). You can use an existing function’s name, as you’ll learn about later in the chapter, but until you understand when and why you might do that, you should stick with unique and obvious function names.
The arguments that a function takes make for a more complicated subject, which will be covered in a few pages. For now, keep in mind that if a function takes no arguments, the parentheses are left blank.
With all of this information in mind, this function prototype defines a function called sayHello that takes no arguments and returns no values:
void sayHello();
The second step in creating your own functions, after declaring the prototype, is to actually define the function itself. This is also called implementing the function. The syntax starts exactly like the prototype but concludes with the body where the actual stuff happens.
void sayHello() {
std::cout << "Hello.";
}
Once your function is prototyped and defined, you call it like any other:
sayHello();
Before running through an example, let’s take a look at how a whole C++ file would be arranged. A function’s prototype is normally placed before the definition of the main()
function. This way, the compiler already knows the function’s syntax when it examines the function call within main()
. After the main()
function, the user-defined functions are then fully listed.
Your C++ file will look something like this:
#include statements
function prototypes
int main() {
// Do whatever.
// Call your functions.
}
function definitions
The question that you are hopefully asking by this point is “When should I define my own functions?” Good question! In general, you’ll want to define your own function when you have a sequence of code—some sort of process—that you repeatedly use or could be naturally separated out. You should not define your own function if it already exists in C++!
You’ll make several of your own functions in this chapter. The first example will do one of the things that most of the applications in this book have done: prompt the user and then wait for them to print Enter or Return before continuing. Here, you will take that code and turn that into a function.
// prompt.cpp - Script 5.1
#include <iostream>
void promptAndWait();
The new function being defined is called promptAndWait. It takes no arguments (the parentheses are empty) and returns no value (indicated by the void
).
int main() {
Even though this application has a user-defined function, it still requires a main()
function. Remember that the main()
function is automatically called when an application is executed, so the core of any application must still go here.
main()
function do something.
std::cout << "The main() function is doing something...
";
Since the purpose of this application is to demonstrate the process of defining and using your own functions, it won’t do much else. If you’d like, have the main()
function do something like convert some numbers from one unit to another, take user input, or whatever.
promptAndWait();
To call the function, simply type its name followed by empty parentheses. The line concludes with a semicolon, as does every statement in C++.
main()
function.
return 0;
} // End of the main() function.
When your applications contain multiple functions, you may find it useful to comment on where each function terminates.
main()
function, begin defining the promptAndWait()
function.
void promptAndWait() {
The definition begins exactly like the prototype. Instead of concluding with a semicolon, the definition itself then has a curly brace, which marks the start of the function’s contents.
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
The function prompts the user to press Enter or Return and then waits until that happens. If your main()
function takes some input (which this program in the book does not), you’ll probably want to add
std::cin.ignore(100, '
'),
or
std::cin.ignore(std::gcount()+1);
as the first line in the function. This is in case a leftover Return or other character is sitting around (see the preceding chapter for more about the need for, or syntax of, this code).
promptAndWait()
function.
} // End of promptAndWait() function.
This closing brace marks the end of the function definition. We’ve added a comment so that it’s clear where the function begins and ends. Notice as well that there’s no return
statement here, as this function returns nothing.
prompt.cpp
, compile, and run the application (Figure 5.1).
• If a program makes use of the same function several times, or if you have a function or set of functions that you use in many applications, you’ll want to place these in their own library file. You’ll learn more about this in Chapter 12, “Namespaces and Modularization.”
• Programmers have many theories as to how you should name your functions, mostly because coming up with theories is what programmers do. The only critical rule is that you use a consistent naming scheme (promptAndWait or prompt_and_wait or PromptAndWait are all perfectly valid; just don’t use promptAndWait as one function name but do_this_and_that as another). Naturally, your function’s name should in itself indicate what that function does.
• Being able to define your own functions is also an important aspect of object-oriented programming. As you’ll discover in Chapter 7, “Introducing Objects,” the object data type can have its own functions, which are called methods.
The simple promptAndWait()
function works just fine and is a decent use of the concept, but there is so much more you can do with user-defined functions. The next feature to incorporate is the ability for a function to take arguments. Arguments, in case it’s not clear, are values that can be passed to a function so that the function can use them. For example, you’ve used the getline()
function with two arguments: the input source (e.g., cin
) and a string variable to which keyed input should be assigned.
To have your functions take arguments, list the argument type and name within the function’s parentheses:
// Prototype:
void factorial (unsigned short num);
// Definition:
void factorial (unsigned short num) {
// Function body.
// Use num.
}
To have a function take multiple arguments, separate each argument from the next by a comma, indicating each type and name individually:
void exponent (int num, int power);
(This function already exists in C++ as pow()
, see Chapter 3, “Operators and Control Structures”; it’s just a syntactical example here.)
When calling a function that takes arguments, you need to pass it the appropriate values. As you’ve already seen, there are many ways of doing this, from passing literal values to variables to the results of calculations. Each of these function calls would be valid:
int n = 2;
int x = 3;
exponent (n, x);
exponent (n, 5);
exponent (3, 4);
It’s important to remember that the values passed to the function must be of the right type and order. In other words, the first value passed to a function will be assigned to the function’s first argument variable, and the second to the second, and so on. There’s no way to pass a value to the second function argument without passing something to the first.
In our next example, a user-defined function will take two arguments: a temperature in degrees and a single character indicating whether the temperature is in degrees Celsius or Fahrenheit. The function will then make the proper conversion and print the results, as you’ve done several times before.
// temperature.cpp - Script 5.2
#include <iostream>
void promptAndWait();
void convertTemperature(float tempIn, char typeIn);
The new function being defined is called convertTemperature. It takes two arguments, the first being a float
and the second being a char
. The promptAndWait()
function will be defined and used in this program, too.
main()
function.
int main() {
float temperatureIn;
char tempTypeIn;
The main()
function needs two variables for storing the user input.
std::cout << "Enter a temperature and indicate whether it is in degrees Fahrenheit or Celsius: [##.# C/F] ";
std::cin >> temperatureIn >> tempTypeIn;
In Chapter 4, “Input, Output, and Files,” you saw how to take input, using an example just like this. First cin
will attempt to read in a float and assign this to temperatureIn
. Then a single character will be read into tempTypeIn
.
if (
(tempTypeIn == 'C') ||
(tempTypeIn == 'c') ||
(tempTypeIn == 'F') ||
(tempTypeIn == 'f')
) {
convertTemperature (temperatureIn, tempTypeIn);
In this version of the program, a little validation is being used to make sure that the tempTypeIn
variable has an acceptable value. You can certainly do more validation than this; see Chapter 4 for examples. The important thing to remember when using your own functions is that the data sent to them must still be validated somehow (unless the purpose of the function is validation).
if
conditional.
} else {
std::cout << "The calculation could not be made due to invalid input.
";
}
If tempTypeIn
does not have one of the acceptable values, the convertTemperature()
function is not called and the problem is reported (Figure 5.2). Going back to the examples in Chapter 4, you could alternatively repeat the prompt and retake the user input.
main()
function.
promptAndWait();
return 0;
}
main()
function, define the promptAndWait()
function.
void promptAndWait() {
std::cin.ignore(100, '
'),
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
}
This code is slightly different than it was in prompt.cpp
(Script 5.1) but will be used the same way. Because this program takes some input, the call to the ignore()
function will help get rid of potential extraneous input.
convertTemperature()
function.
void convertTemperature(float tempIn, char typeIn) {
As the prototype also indicates, the function takes two arguments. The first is a float called tempIn
. The value of temperatureIn
, which is the first argument provided when this function is called from main()
, will be assigned to tempIn
here. The same goes for typeIn
, which receives the value of tempTypeIn
from main()
.
const unsigned short ADD_SUBTRACT = 32;
const float RATIO = 5.0/9.0;
float tempOut;
char typeOut;
The two constants are needed for the actual conversion, whereas the two variables are used in the output. Again, this is similar to how this conversion was written in previous programs.
switch (typeIn) {
case 'C':
case 'c':
tempOut = (tempIn / RATIO) + ADD_SUBTRACT;
typeOut = 'F';
break;
case 'F':
case 'f':
tempOut = (tempIn - ADD_SUBTRACT) * RATIO;
typeOut = 'C';
break;
}
There’s nothing new here; the temperature is just calculated according to whether the input is in degrees Celsius or Fahrenheit.
std::cout << tempIn << " degrees "
<< typeIn << " is equal to "
<< tempOut << " degrees "
<< typeOut << ".
";
}
temperature.cpp
, compile, and run the application (Figures 5.3 and 5.4).
• Technically, in C++ you do not need to name the arguments in the function prototype, but it is a good idea.
• You’ll see and hear the terms parameters and arguments used synonymously. They can both be used to refer to values sent to, and received by, a function when it is called.
• If you come from a C background, you’ll recognize that C and C++ indicate function arguments differently. Take the definition
void functionName();
In C, this indicates an unspecified number and type of arguments. In C++, it means that the function takes no arguments. The equivalent of that in C is
void functionName (void);
You can also use this construct in C++, if you prefer to be more explicit.
• If your function takes several arguments of the same type, you cannot use the variable declaration shortcut of separating each by a comma:
int n1, n2; // Valid
This is invalid:
void functionName (int n1, n2);
This is valid:
void functionName (int n1, int n2);
A second way in which you can modify your function definition is by establishing a default value for an argument. The benefit of a default value is that it makes the argument optional. To do this, assign the argument variable a value within the function prototype (but not the definition) using the assignment operator:
void fN (int n1, int n2 = 6);
With this function definition, either of these function calls is valid:
fN (1);
fN (5, 20);
If an argument with a default value is passed a value as in the second example, that value will be used. If no value is passed, the default is used. So in the first example, n2
will have a value of 6
within the function. In the second example, n2
will have a value of 20
.
Your functions can have as many arguments with default values as you want, but there is one trick: every required argument must come before the optional arguments. As examples, these two definitions are fine:
void fN (int n1, int n2 = 6, int n3 = 4);
void fN (int n1 = 1, int n2 = 6);
But these are not:
void fN (int n1 = 1, int n2); // NO!
void fN (int n1, int n2 = 6, int n3); // NO!
In this next example, a currency conversion function will be defined that turns U.S. dollars into Euros and prints the results. The function will take two arguments: a conversion rate and the number of dollars being converted, with 1
as the default value.
// currency.cpp - Script 5.3
#include <iostream>
void promptAndWait();
void dollarsToEuros(float rate, unsigned dollars = 1);
The only significant difference between the convertTemperature()
function defined in the previous program and this dollarsToEuros()
function is the use of a default argument value. The dollars
variable will have a default value of 1
, unless a new value is passed to the function when it is called.
main()
function.
int main() {
float conversionRate = 0.832339;
unsigned dollarsIn;
For sake of simplicity, the conversion rate is defined as a variable in the program, as opposed to being taken as user input. The unsigned integer dollarsIn
will store the user-submitted dollar amount.
dollarsToEuros(conversionRate);
When we call the function while providing only one argument, the default value of dollars
—which is 1
—will be used. The effect of this will be a heading that shows the conversion rate (Figure 5.5).
std::cout << "Enter a US dollar amount (without the dollar sign, commas or a decimal): [####] ";
std::cin >> dollarsIn;
The intent of the program is to read in a dollar amount from the user and then convert this into Euros. Here the user is prompted and the dollars are read in (Figure 5.6).
dollarsToEuros(conversionRate, dollarsIn);
The dollarsToEuros()
function is called again, this time providing it with the user-submitted dollar amount. Thus, the conversion will use dollarsIn
number of dollars, not the default of 1
.
main()
function.
promptAndWait();
return 0;
}
promptAndWait()
function.
void promptAndWait() {
std::cin.ignore(100, '
'),
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
}
dollarsToEuros()
function.
void dollarsToEuros(float rate, unsigned dollars) {
Remember that you do not want to establish the default argument values here, as that syntax would be incorrect. You only set the default values in the function prototype.
std::cout.setf(std::ios_base::fixed);
std::cout.setf(std::ios_base::showpoint);
std::cout.precision(2);
Because the results of the calculation will be a float (obtained by multiplying the float rate times the integer dollars), you’ll want to format the output. This code was introduced in Chapter 2, “Simple Variables and Data Types.” It states that a fixed decimal point should be used, that it should always be shown, and that it should contain exactly two numbers after the decimal.
std::cout << "
$" << dollars
<< " US = " << (rate * dollars)
<< " Euros.
";
}
This part of the function should be pretty obvious to you, mostly just a matter of multiplying the conversion rate by the number of dollars. Newlines are added at the beginning and end of the printed text so that it looks nicer in the output.
currency.cpp
, compile, and run the application (Figure 5.7).
• The ability to set default argument values is another addition in C++ that is not present in C.
• Some programmers prefer to also have the default value indicated in a function’s definition. To do so, comment out the value assignment:
void fN (int n1, int n2 /* = 6 */) {
// Function body.
}
There is one last thing that many C++ functions do that has not yet been discussed: they often (but not always) return some sort of value. The size()
function used on strings returns the number of characters in a string, and the pow()
function, defined within the cmath
file, returns a number to a certain power. To have your own functions return a value, use the return
statement, as you already have been doing in the main()
function. You can return any single value from a function:
return 1;
The returned value can even be based on a variable:
int num = 6.25;
return num;
Besides using return
in the function, both the function prototype and its definition must indicate what type of value will be returned. You do so by preceding the function name with a type identifier, as in
// Prototype:
float multiply (float x, float y);
// Definition:
float multiply (float x, float y) {
return x * y;
}
You can assign the returned values to variables when the function is called, use them in calculations, or even use them as the argument to another function:
float num = multiply (2.6, 890.245);
float sum = num + multiply (0.32, 6874.1);
std::cout << multiply (0.5, 32.2);
To demonstrate this, the next example will take an integer as its lone argument and return its factorial value. In case you don’t remember from the previous factorial example, in Chapter 3, the factorial is represented in math as n!
and is equal to every number from 1
to n
multiplied together (so 4!
is equal to 1 * 2 * 3 * 4
).
// factorial.cpp - Script 5.4
#include <iostream>
void promptAndWait();
unsigned long returnFactorial(unsigned short num);
The new function, returnFactorial()
, takes one argument, in the form of an unsigned short integer called num
. This function returns a value, which will be an unsigned long integer. These two data types are appropriate, as the factorial of even a small number will quickly near the maximum size of a long integer.
main()
function.
int main() {
unsigned short numberIn;
The main part of the program requires one variable, which will store the user-submitted number. Its type—unsigned short—matches what will be sent to the returnFactorial()
function.
numberIn
.
std::cout << "Enter a small, positive integer: [##] ";
std::cin >> numberIn;
At this point you could also perform some validation, such as making sure that an unsigned integer between 1 and 12 was entered. The latter would be a good upper limit, as 13!
eclipses the maximum long integer value on 32-bit computers.
(If that last statement doesn’t make sense right now, you’ll see specifically how this plays out in Chapter 10, “Error Handling and Debugging.”)
std::cout << "The factorial of " << numberIn
<< " is " << returnFactorial (numberIn) << ".
";
The inputted number is sent back to the output along with the calculated factorial (Figure 5.8). Since the returnFactorial()
function returns a value, the function call can be placed within a cout
statement, as it is here. The end result will be that the value returned by the function will be sent to the output stream.
main()
function.
promptAndWait();
return 0;
}
promptAndWait()
function.
void promptAndWait() {
std::cin.ignore(100, '
'),
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
}
returnFactorial()
function.
unsigned long returnFactorial (unsigned short num) {
The definition begins exactly like its prototype.
unsigned long sum = 1;
for (int i = 1; i <= num; ++i) {
sum *= i;
}
The syntax for this calculation was introduced in Chapter 3. Every number between 1 and the submitted number has to be multiplied together. To do so, sum
is initialized as 1
and then assigned the value of itself times i
.
return sum;
}
The sum
variable has the value of the calculated factorial and can now be returned. Notice that the data type of sum
—unsigned long integer—matches the return type for the function.
factorial.cpp
, compile, and run the application (Figure 5.9).
• You can have multiple return
statements in a function, but only one return
statement will ever be executed. A common example is something like
if (condition) {
return 1;
} else {
return 0;
}
• The return
statement stops the execution of a function. Any code after an executed return
will never be executed:
int myF () {
return 1;
std::cout << "Function returned 1";
}
The Function returned 1 message will never be printed as the std::cout
line will not be executed.
• To be really formal, you can use
return;
in a function that returns no values.
Overloading functions in C++ is a slightly more advanced topic than what you’ve seen so far but is at the heart of the language’s flexibility and power. Overloading a function is the process of defining a function with the same name (and the same purpose) but with different arguments, either in number or in type. If you take a look at the convertTemperature()
function (see Script 5.2), you may see why this would be necessary.
As it stands, the function takes one float
argument and another char
. But what if you wanted to convert an integer? You couldn’t do that with this version of the function because it accepts a float (the function call would still work, but the number 64
would be received as 64.0
: a float, not an integer). You could create a different function, say convertIntegerTemperature()
, but then your program would need to call one function in one circumstance and another function otherwise. A better solution is to just define the function again, but this time so that it can take an integer value.
The two prototypes would look like this:
void convertTemperature (float tempIn, char typeIn);
void convertTemperature (int tempIn, char typeIn);
Once you’ve defined an overloaded function, which definition gets used will be determined by the arguments in the function call.
convertTemperature (54.9, 'F'),
convertTemperature (16, 'C'),
Both functions would, in this case, have the same contents, but the right version would be called in each of these cases.
The final question, then, is when would you want to use this? For the most part, overloaded functions are used so that the same process can handle different data types. Thus one definition of myFunction()
would accept integers, another would accept real numbers, and so on. This is demonstrated in the preceding example and in the following program. You’ll also see the concept, as well as the similar idea of overriding a function, when it comes to working with objects in Chapter 7, “Introducing Objects,” and Chapter 8, “Class Inheritance.”
currency.cpp
(Script 5.3) in your text editor or IDE.dollarsToEuros()
so that dollars
no longer has a default value (Script 5.5).
void dollarsToEuros(float rate, unsigned dollars);
Relying upon default values with overloaded functions can cause ambiguity problems, so that part of the function will be removed.
dollarsToEuros()
prototype.
void dollarsToEuros(float rate, float dollars);
This prototype is exactly the same in every way except for the type of the second argument. Remember that function names are case sensitive, so the spelling and capitalization must exactly match.
main()
function, declare another variable.
float dollarsInFloat;
To test the overloading concept, this program will first take integer input, and then a real number input. The latter will be stored in this variable.
The next three steps will all require edits within the main()
function as well.
dollarsToEuros()
.
In the original version of this application, the function was called once to use the default dollar value. As it stands, if you did that with two function definitions (assuming both had a default argument value for dollars
), you’d see an error, as the compiler wouldn’t know which function was being called (Figure 5.10).
std::cout << "Enter a US dollar amount (without the dollar sign or commas): [####.##] ";
std::cin >> dollarsInFloat;
dollarsToEuros()
function using the float as the second argument.
dollarsToEuros(conversionRate, dollarsInFloat);
Because dollarsInFloat
is a float, this line will call the second definition of dollarsToEuros()
.
dollarsToEuros()
definition.
void dollarsToEuros(float rate, float dollars) {
std::cout.setf(std::ios_base::fixed);
std::cout.setf(std::ios_base::showpoint);
std::cout.precision(2);
std::cout << "
$" << dollars
<< " US = " << (rate * dollars)
<< " Euros.
";
}
The only difference here is that the second argument is of type float
.
overload.cpp
, compile, and run the application (Figure 5.11).
• You could also modify both dollarsToEuros()
functions so that they return the converted amount instead of printing it. Another alteration you could make is to ignore any existing input before reading in the dollars the second time. As it stands, if a user enters 300.75
for the first number, cin
assigns just 300
(the integer) to dollarsIn
, leaving .75
in the buffer which will be read in as the float (Figure 5.12).
• You cannot overload a function by just modifying the type of value returned, although an overloaded function may also differ in this way.
• Since the dollarsToEuros()
function has only two arguments and it is the second argument that differs between the two definitions, you might want to switch the arguments around—put the dollars first, then the rate—so that it’s more obvious how they differ.
• To re-stress the point, normally you’ll use overloaded functions so that the same process can handle different data types. If you just need a function that may take, say, two arguments or three, then defining one function whose third argument is optional (because it has a default value) is the better way to go.
Now that you have an understanding of writing and using your own functions, it’s time to revisit the topic of variables. This hasn’t been discussed before, but variables have a scope: a realm in which they exist. As you’ve seen, once you’ve declared a variable, you can refer to it, but where you can refer to that variable is dependent upon where it was defined. Here are some rules to go by:
• A variable defined within a code block is only available within that code block. A block is a group of instructions grouped together within curly braces, like a conditional, a loop, or even:
{
// This is a block.
}
• A variable defined within a function is only available within that function. These are called local variables.
• Variables defined outside of any function are accessible within any function defined thereafter. These are called global variables.
The first rule can be demonstrated with the following code:
for (int i = 1; i <= 10; ++ i) {
std::cout << i << "
";
}
/* i no longer exists outside of the loop! */
Or, a less useful example:
if (1) {
bool isTrue = true;
} // isTrue no longer exists!
With respect to the second rule, a global variable is defined outside of a function:
unsigned short age = 60;
int main() {...}
void sayHello() {...}
Both the main()
and sayHello()
functions can refer to age
, as it has global scope.
The third rule really trips up the beginner programmer, so a demonstration will be written to illustrate the concept of variable scope. This demonstration will also make use of a global variable, so you can see how they differ from local ones.
// scope.cpp - Script 5.6
#include <iostream>
#include <string>
This program also includes the string
header file, as it will use variables of that type.
void promptAndWait();
void nameChange();
The new function, nameChange()
, takes no arguments and returns no values. It will be used to highlight the differences between variables within main(),
variables within other functions, and variables outside of functions.
std::string gName;
This variable, defined outside of any function, will be available within any function defined after this point.
main()
function.
int main() {
std::string name = "Andi";
The variable name
is local to the main()
function. It can now be used anywhere within this function from this point onward (until the curly brace that closes the function).
gName
and print both variables.
gName = name;
std::cout << "At first, name is " << name << " and gName is " << gName << ".
";
In the first line, the gName
variable, which is global, is assigned the value of the name
variable. So both variables now have the same value. This will be confirmed by printing both.
nameChange()
function and then print the values of the variables again.
nameChange();
std::cout << "After the function, name is " << name << " and gName is " << gName << ".
";
As you’ll soon see, the nameChange()
function will assign values to two variables. To confirm how that affects the variables accessible within main()
, another cout
line is included after calling the function.
main()
function.
promptAndWait();
return 0;
}
promptAndWait()
function.
void promptAndWait() {
std::cout << "Press Enter or Return to continue.
";
std::cin.get();
}
As with the first example in this chapter, the ignore()
function has been omitted, as the application takes no input.
nameChange()
function.
void nameChange() {
std::string name = "Larry";
This function has its own variable called name
. Although this variable has the same identifier and is of the same type as the name
variable in the main()
function, these are two separate and unrelated variables.
std::cout << "In the function, name is " << name << " and gName is initially " << gName << ".
";
gName
and print both variables again.
gName = name;
std::cout << "In the function, name is " << name << " and gName is now " << gName << ".
";
The first line assigns the value of name
(which is Larry in this function) to the global variable gName
. Both variables are then printed.
}
scope.cpp
, compile, and run the application (Figure 5.13).
• Even when you use a variable in a function call, like this:
int myVar = 20;
fN(myVar);
you are not truly passing that variable to the second function but rather that variable’s value. In the preceding code, the myVar
variable still doesn’t exist within the someFunction()
function.
• For that matter, suppose you have
void fN(int myVar);
int main() {
int myVar = 20;
fN(myVar);
}void fN(int myVar) {
// Do whatever.
}
The myVar
defined within the main()
function and used in calling fN()
is still different than the myVar
that is the argument in fN()
.
• You might think that since global variables exist everywhere, it would be best to use nothing but global variables. Although this makes it easier for you, the programmer, it’s poor form.
• Be extra careful not to give global and local variables the same name. If you do, the local variable will take precedence within that function or code block and the global variable will not be available at that point.
• One way to work around variable scope is to pass values to a function by reference instead of by value. This requires pointers and addresses, which you’ll learn about in Chapter 6, “Complex Data Types.”