Void (NonValue-Returning) functions:
Similarities Between Value-Returning and Void (NonValue-Returning) functions:Void functions are created and used just like value-returning functions except they do not return a value after the function executes. In lieu of a data type, void functions use the keyword "void." A void function performs a task, and then control returns back to the caller--but, it does not return a value. You may or may not use the return statement, as there is no return value. Even without the return statement, control will return to the caller automatically at the end of the function. A good utilization of a void function would be to print a header/footer to a screen or file.
Remember: there are two kinds of subprograms that the C++ language utilizes: value-returning functions and void functions. Both value-returning functions and void functions receive values through their parameter lists. A value-returning function can only return one value to the calling environment. The caller invokes (calls) a value-returning function by using its name and argument list in an expression (i.e., 1. assignment, 2. output, or as an 3. argument in another function call)://value-returning function call (assignment): y = 2.0 * sqrt(x);In contrast, a void function (method or procedure, in other languages) does not return a function value. Nor is it called from within an expression. Instead, the function call appears as a complete, stand-alone statement. One example is the get function associated with the istream and ifstream classes://void function call: cin.get();Another example://void function call: printName(name);Bjarne Stroustrup's C++ Glossary
//Void (NonValue-returning) function definition syntax: including header and body void functionName(formal parameter list) //function header { //function body statements... //void (nonvalue-returning) function can still use return statement //but, does not return any values... return; } //function call syntax: functionName(actual parameter list); //stand-alone statement only
functionName(); //stand-alone statement only
Function Parameter Types:
Two Types of Function Parameters:
//Void (NonValue-returning) function definition syntax: including header and body void functionName(dataType variable, dataType variable) //function header { //function body statements... //void (nonvalue-returning) function can still use return statement //but, does not return any values... return; }
//Void (NonValue-returning) function definition syntax: including header and body void functionName(dataType& variable, dataType& variable) //function header { //function body statements... //void (nonvalue-returning) function can still use return statement //but, does not return any values... return; }
//Void (NonValue-returning) function call with arguments functionName(expression or constant or variable, expression or constant or variable); //stand-alone statement only
//Void (NonValue-returning) function call with arguments functionName(variable, variable); //stand-alone statement only
When a function is called:
Program demos void functions using value and reference parameters:Note: Although the C++ language allows value-returning functions to have both value parameters and reference parameters, it is not recommended. By definition, a value-returning function returns a single value; this value is returned via the return statement. Use void functions with reference parameters to return (modify) more than one value.
/* This program demos void functions using value parameters vs. reference parameters Reference Parameter: If a formal parameter is a reference parameter, it receives the address of the corresponding actual parameter A reference parameter stores the address of the corresponding actual parameter During program execution to manipulate the data, the address stored in the reference parameter directs it to the memory space of the corresponding actual parameter */ //header files #include<iostream> using std::cout; using std::cin; using std::endl; //prototype functions void readDate(int& month, int& day, int& year); //reference parameters void printDate(int month, int day, int year); //value parameters //initialize constants //initialize global variables int main() { //initialize automatic variables int mm, dd, yy; readDate(mm, dd, yy); printDate(mm, dd, yy); cout << "Press Enter key to exit..."; cin.get(); cin.get(); // make DOS window stay open return 0; } //function definitions void readDate(int& month, int& day, int& year) { char ch; //local variable cout << "Enter a date (mm/dd/year): "; cin >> month >> ch >> day >> ch >> year; } void printDate(int month, int day, int year) { cout << "The date is " << month << '-' << day; cout << '-' << year << endl; }
When to use Void or Value-Returning Functions:
What is scope?
A global variable, that is a variable declared outside of all functions in a file, is accessible by any code in that file. By declaring extern variables, for programs that require multiple files, variables declared in one file can be accessible in other files. Variables that are declared as extern are often placed in an include file that is used by any file requiring access to the external variable. If there are multiple variables with the same name whose scopes overlap at one point in a program, the variable with the innermost scope will be used.
// scopes: // x i j k float x; // | int main() // | { // | int i; // | | for (int j = 0; j < 100; ++j) // | | | { // | | | std::cin >> i; // | | | int k = i; // | | | | // more code // | | | | } // | | return 0; // | | } // | Note that x is global, i and j are local. The following code is more subtle. #include <iostream> int main() { std::cout << "\nStarting Program\n"; { int x = 5;// declare new variable std::cout << "x = " << x << '\n'; { int x = 8; std::cout << "x = " << x << '\n'; } std::cout << "x = " << x << '\n'; { x = 3; } std::cout << "x = " << x << '\n'; } } You can run the program to be sure you understand how scope rules affect the values of the variables.
std::cout << "Namespace test";
using std::cout; cout << "Namespace test";
using namespace std; cout << "Namespace test";
Global Variables
- Since global variables are shared by different modules, they make each of these modules more difficult to understand separately, diminishing readability and hence hampering maintenance.
- As global variables constitute a form of undercover dependency between modules, they are a major obstacle to software evolution, since they make it harder to modify a module without impacting others.
- They are a major source of nasty errors. Through a global variable, an error in a module may propagate to many others. As a result, the manifestation of the error may be quite remote from its cause in the software architecture, making it very hard to trace down errors and correct them. This problem is particularly serious in environments where incorrect array references may pollute other data.
- There is also another problem, less fundamental but still annoying: since a global variable does not belong to any one module in particular, it is not clear where it should be initialized.
What is lifetime?
static dataType identifier; static int x; //static variable of type int
Using Stub Functions:
Stub functions may be used when testing programs. A stub function is a stripped-down, skeletal structure of the actual function. It does not implement the full details of the algorithm or function requirements. It does contain the parameter lists. Essentially, a stub is a dummy function with a limited body, usually just output statements that acknowledge the function was reached, and a return value (if any) of the correct type. Usually, the stub function's name and parameter list is the same as the function that will actually be called by the program being tested.
What is Function Overloading:
Function Overloading Example:Several functions with the same name is called function overloading. Generally, function overloading is used when different data types will be used with the same function. As an illustration, one function may accept integer values, while another can receive char or float data. Of course, you could implement the same functionality using a different function name whose parameters would receive the various data types--or, you can employ function overloading.
When overloading a function, dissimilar signatures (i.e., different "TON": type, order, or number) must be used for each overloaded version. A function signature consists of a list of data types of its parameters, as well as their order, and number (i.e., the number of parameters).
Lastly, a function differing only by return type, OR different parameter names is illegal (though, it is legal to use a different return type with a different parameter list--that is, different "TON." See below):
//valid overloaded function prototypes (applicable to definitions as well)... void myFunc(); void myFunc(int i); void myFunc(char c); void myFunc(char c, int i); void myFunc(int i, char c); void myFunc(string & s); //Error: differs from void myFunc(); only by return type int myFunc(); //OK: Different "TON" (i.e., unique signature) int myFunc(float f); /* The functions myFunc, using the same number of parameters (two, with just different names), and the same data types (int and char), in the same order, have the same formal parameter list, and, is therefore illegal... */ void myFunc(int myInt, char myChar); //illegal--same "TON"
Using Functions with Default Parameters:
Functions with Default Parameters Example:When a function is called, the number of actual and formal parameters must be the same except in the case of default parameters. The value of a default parameter is specified when the function name appears for the first time (as in the prototype).
The following rules apply to default parameters:
- Specify default parameter values when function name appears for first time (as in the prototype)
- If no default parameter value is specified, the default value is used
- All default parameters must be the rightmost parameters of function
- In function call where function has more than one default parameter, and a value to a default parameter is not specified, must omit all of arguments to its right
- Default values can be constants, global variables, or function calls
- Caller has option of specifying a value other than the default for any default parameter
- Cannot assign constant value as default value to reference parameter
//function prototype...applies to definitions as well... void myFunc(int x, int y, double t, char z = 'A', int u = 50, char v='B', double w = 18.56); //local variables int a, b; char ch; double d; //legal function calls myFunc(a, b, d); myFunc(a, 15, 36.1, 'C', 92, ch); myFunc(b, a, 13.21, 'D'); //illegal function calls myFunc(a, 15, 33.1, 62.3); myFunc(b, 25, 32.9, 'E', 1234, 92.7);
A Recursive Function: