Hiding data is an important component of OOP. You need to give careful consideration to which components should be left public and which should be left private. In general, data members are private, with the functions that allow you to examine and change them kept public.
If too much is left public, then tampering and misuse of implementation details can result.
If too much is left private, then inefficiencies and access problems can result. If you properly gauge public and private portions of an object, then code is more easily debugged and maintained because errors and modifications are localized.
Client programs need only be aware of the type's public interface specification.
Objects encapsulate data and implementation and the user of an object can view the object as a black box that provides services.
Black Box versus White-Box Testing
Testing the functionality of the program without consideration of its internal structure is called black-box testing.
This is an important part of testing, because, the users of a program do not know its internal structure.
If a program works perfectly on all positive inputs and fails gracefully on all negative ones, then its function is fulfilled.
It is impossible to ensure absolutely that a program will work correctly on all inputs, just by supplying a finite number of test cases.
As the famous computer scientist Edsger Dijkstra pointed out, testing can only show the presence of bugs, not their absence.
To gain more confidence in the correctness of a program, it is useful to consider its internal structure.
Testing strategies that look inside a program are called white-box testing.
Performing unit tests of each procedure and function is a part of white-box testing.
Functions as Black Boxes
Parameter values are supplied in the function call. The return value is the result that the function computes.
When you use sqrt(x) inside main, the input or parameter value x is transferred, or passed, to the sqrt function.
The execution of the main function is temporarily suspended.
The sqrt function becomes active and computes the output or return value which is the square root of the input value.
Using some method that (we trust) will yield the correct result. That return value is transferred back to main, which resumes the computation using the return value.
The input value to a function need not be a single variable; it can be any expression, as in
sqrt(b * b - 4 * a * c).
Figure 2-10.2 shows the flow of execution when a function is called.
Some functions have more than one input. For example, the pow function has two parameters: pow(x, y) computes xy. Functions can have multiple inputs, but they only have one output.
Each function takes inputs of particular types. For example, sqrt receives only numbers as parameter values,
whereas getline expects a stream and a string. It is an error to call sqrt with a string input.
Each function returns a value of a particular type: sqrt returns a floating-point number, substr returns a string, and main returns an integer.