Functions
- The best way to develop and maintain a large program is to divide it into several smaller program modules each of which is more manageable than the original program. Modules are written in C++ classes and functions.
- A function is invoked by a function call. The function call mentions the function by name and provides information (as arguments) that the called function needs to perform its task.
- The purpose of information hiding is for functions to have access only to the information they need to complete their tasks. This is a means of implementing the principle of least privilege, one of the most important principles of good software engineering.
- Functions are normally invoked in a program by writing the name of the function followed by the arguments of the function in parentheses.
- Data type double is a floating-point type like float. A variable of type double can store a value of much greater magnitude and precision than float can store.
- Each argument of a function may be constant, a variable, or an expression.
- A local variable is known only in a function definition. Functions are not allowed to know the implementation details of any other function (including local variables).
- The general format for a function definition is
- Return-value-type function-name( parameter-list )
- {
- declarations and statements
}
- The return-value-type states the type of the value returned to the calling function. If a function does not return a value, the return-value-type is declared void. The function-name is any valid identifier. The parameter-list is a comma-separated list containing the declarations of the variables that will be passed to the function. If a function does not receive any values, parameter-list is declared as void. The function-body is the set of declarations and statements that constitute the function.
- The arguments passed to a function should match in number, type, and order with the parameters in the function definition.
- When a program encounters a function, control is transferred from the point of invocation to the called function, the function is executed, and control returns to the caller.
- A called function can return a control to the caller in one of three ways. If the function does not return a value, control is returned when the function-ending right brace is reached, or by executing the statement, return; If the function does return a value, the statement return expression; returns the value of expression.
- A function prototype declares the return-type of the function and declares the number, the types, and order of the parameters the function expects to receive.
- Function prototypes enable the compiler to verify that functions are called correctly.
- The compiler ignores variable names mentioned in the function prototype.
- Each standard library has a corresponding header file containing the function prototypes for all the functions in that library, as well as definitions of various symbolic constants needed by those functions.
- Programmers can and should create and include their own header files.
- When an argument is passed call-by-value, a copy of the variable's value is made and the copy is passed to the called function. Changes to the copy in the called function do not affect the original variable's value.
- The rand function generates an integer between 0 and RAND_MAX which is defined to be at least 32767.
- The function prototypes for rand and srand are contained in <stdlib.h>.
- Values produced by rand can be scaled and shifted to produce values in a specific range.
- To randomize a program, use the standard library function srand.
- The srand statement is ordinarily inserted in a program only after the program has been thoroughly debugged. While debugging, it is better to omit srand. This ensures repeatability, which is essential to proving that corrections to a random number generation program work properly.
- To randomize without the need for entering a seed each time, we may use srand( time ( 0 ) ). The time function normally returns "calendar time" in seconds. The time function prototype is located in the header <time.h>.
- The general equation for scaling and shifting a random number is n = a + rand ( ) % b; where a is the shifting value (which is equal to the width of the desired range of consecutive integers).
- An enumeration, introduced by the keyword enum and followed by a type name, is a set of integer constants represented by indentifiers.
- The values of these enumeration constants start at 0, unless specified otherwise, and are incremented by 1.
- The identifiers in an enum must be unique, but separate enumeration constants can have the same integer value.
- Any enumeration constant can be explicitly assigned an integer value in the enumeration definition.
- Each variable identifier has the attributes storage class, scope, and linkage.
- C++ provides for storage class specifiers; auto, register, extern, and static.
- An identifier's storage class determines when that identifier exists in memory.
- A identifier's scope is where the identifier can be referenced in a program.
- An identifier's linkage determines for a multiple-source-file program if an identifier is known only in the current source file or in any source file with proper declarations.
- Variables of automatic storage class are created when the block in which they are declared in enteres, exist while the block is active, and are destroyed when the block is exited. A function's local variables normally are of automatic storage class.
- The storage class specifier register can be placed before an automatic variable declaration to suggest that the compiler maintain the variable in one of the computer's highspeed hardware registers. The compiler may ignore register declarations. The register keyword can be used only with variable of the automatic storage class.
- The keywords extern and static are used to declare identifiers for variables and functions of the static storage class.
- Static storage class variables are allocated and initialized when the program begins execution.
- Two types of identifiers have static storage class: external identifiers and local variables declared with the storage class specifier static.
- Global variables are created by placing variable declarations outside any function definition, and they return their values throughout the execution of the program.
- Local variables declared static retain their value when the function in which they are declared is exited.
- All numeric variables of static storage class are initialized to zero if they are not explicitly initialized by the programmer.
- The four scopes for an identifier are function scope, file scope, block scope, and function-prototype scope.
- Labels are the only identifiers with function scope. Labels can be used anywhere in the function in which they appear, but cannot be referenced outside the function body.
- An identifier declared outside any function has file scope. Such an identifier is "known" from the point at which the identifier is declared until the end of the file.
- Identifiers declared inside a block have block scope. Block scope ends at the terminating right brace (}) of the block.
- Local variables declared at the beginning of a function have block scope as do function parameters, which are considered local variables by the function.
- Any block may contain variable declarations. When block are nested, and an identifier in an outer block has the same name as an identifier in an inner block, the identifier in the outer block is "hidden" until the inner block terminates.
- The only identifiers with function-prototype scope are those used in the parameter list of a function prototype. Identifiers used in a function prototype can be reused elsewhere in the program without ambiguity.
- A recursive function is a function that calls itself either directly or indirectly.
- If a recursive function is called with a base case, the function simply returns a result. If the function is called with a more complex problem, the function divides the problem into two conceptual pieces: a piece that the function knows how to do and a slightly smaller version of the original problem. Because this new problem looks like the original problem, the function launches a recursive call to work on the smaller problem.
- For recursion to terminate, each time the recusive function calls itself with a slightly simpler version of the original problem, the sequence of smaller and smaller problems must converge on the base case. When the function recognizes the base case, the result is returned to the previous function call, and a sequence of returns ensues all the way up the line until the original call of the function eventually returns the final result.
- The ANSI standard does not specify the order in which the operands of most operators are to be evaluated. C++ specifies the order of evaluation of the operands of the operators &&, ||, the common ( , ) operator, and ?:. The first three are binary operators whose operands are evaluated left to right. The last operator is C++'s only ternary operator. Its leftmost operand is evaluated first; if it evaluates to nonzero, the middle operand is evaluated next and the last operand is ignores; if it evaluates to zero, the third operand is evaluated next and the middle operand is ignored.
- Both iteration and recursion are based on a control structure: Iteration uses a repetition structure; recursion used a selection structure.
- Both iteration and recursion involve a termination test: Iteration terminates when the lop-continuation condition fails; recursion terminates when a case is recognized.
- Iteration and recursion can occur infinitely: An infinite loop occurs with iteration if the loop-continuation test never becomes false; infinite recursion occurs if the recursion step does not reduce the problem in a manner that converges on the base case.
- Recursion repeatedly invokes the mechanism and consequently the overhead, of function calls. This can be expensive in both processor time and memory space.
- C++ programs do not compile unless a function prototype is provided for every function or a function is defined before it is used.
- A function that does not return a value is declared with a void return type. An attempt to return a value from the function or to use the result of the function invocation in the calling function is a syntax error.
- An empty parameter list is specified with empty parentheses of void in parentheses.
- Inline functions eliminate function-call overheard. The programmer uses the keyword inline to advise the compiler to generate function code in line (when possible) to minimize function calls. The compiler may choose to ignore the inline advice.
- C++ offers a direct form of call-by-reference using reference parameters. To indicate that a function parameter is passed by reference, follow the parameter's type in the function prototype by an &. In the function call, mention the variable by name and it will be passed call-by-reference. In the called function, mentioning the variable by its local name actually refers to the original variable in the calling function. Thus, the original variable can be modified directly by the called function.
- Reference parameters can also be created for local use as aliases for other variables within a function. Reference variables must be initialized in their declarations, and they can not be reassigned as aliases to other variables. Once a reference variable is declared as an alias for another variable, all operations supposedly performed on the alias are actually performed on the variable.
- C++ allows the programmer to specify default arguments and their default values. If a default argument is omitted in a call to a function, the default value of that argument is used. Default arguments must be the rightmost (trailing) arguments in a function's parameter list. Default arguments should be specified with the first occurrence of the function name. Default values can be constants, global variables, or function calls.
- The unary scope resolution operator ( : : ) enables a program to access a global variable when a local variable of the same name is in scope.
- It is possible to define several functions with the same name but with different parameter types. This is called function overloading. When an overloaded function is called, the compiler selects the proper function by examining the number and types of arguments in the call.
- Overloaded functions can have different return values, and must have different parameter lists. Two functions differing only by return type will result in a compilation error.
- Function templates enable the creation of functions that perform the same operations on different types of data, but the function template is defined only once.