To guarantee that there are enough arguments
on the command line, you see a second function used from the require.h header file:
requireArgs( ), which compares argc to the desired number of arguments and prints an appropriate error message and exits the program if there aren’t enough arguments.
Global scope resolution
The scope resolution operator gets you out of situations where the name the compiler chooses
by default (the “nearest” name) isn’t what you want. For example, suppose you have a
structure with a local identifier a, and you want to select a global identifier a from inside a member function. The compiler would default to choosing the local one, so you must tell it to do otherwise. When you want to specify a global name using scope resolution, you use the
operator with nothing in front of it. Here’s an example that shows global scope resolution for both a variable and a function:
//: C04:Scoperes.cpp {O}
// Global scope resolution
int a;
void f() {}
struct S {
int a;
void f();
};
Chapter 1: Data Abstraction
188
void S::f() {
::f(); // Would be recursive otherwise!
::a++; // Select the global a
a--; // The a at struct scope
}
///:~
Without scope resolution in S::f( ), the compiler would default to selecting the member versions of f( ) and A.
Summary
In this chapter, you’ve learned the fundamental “twist” of C++: that you can place functions
inside of structures. This new type of structure is called an abstract data type, and variables you create using this structure are called objects, or instances, of that type. Calling a member function for an object is called sending a message to that object. The primary action in object-oriented programming is sending messages to objects.
Although packaging data and functions together is a significant benefit for code organization and makes library use easier because it prevents name clashes by hiding the names, there’s a
lot more you can do to make programming safer in C++. In the next chapter, you’ll learn how
to protect some members of a struct so that only you can manipulate them. This establishes a clear boundary between what the user of the structure can change and what only the
programmer may change.
Exercises
1.
In the Standard C library, the function puts( ) prints a char array to the
console (so you can say puts("hello")). Write a C program that uses puts( ) but does not include <stdio.h> or otherwise declare the function. Compile
this program with your C compiler (Some C++ compilers are not distinct
from their C compilers; in this case you may need to discover a command-
line flag that forces a C compilation). Now compile it with the C++
compiler and note the difference.
2.
Create a struct declaration with a single member function; then create a
definition for that member function. Create an object of your new data type,
and call the member function.
3.
Change your solution to the previous exercise so the struct is declared in a
properly “guarded” header file, the definition is in one cpp file and your
main( ) is in another.
Chapter 1: Data Abstraction
189
4.
Create a struct with a single int data member, and two global functions,
each of which takes a pointer to that struct. The first function has a second
int argument and sets the struct’s int to the argument value, the second displays the int from the struct. Test the functions.
5.
Repeat the previous exercise but move the functions so they are member
functions of the struct, and test again.
6.
Write and compile a piece of code that performs data member selection and
a function call using the this keyword (which refers to the address of the
current object).
7.
Make a Stash that holds doubles. Fill it with 25 double values, then print them out to the console.
8.
Repeat the previous exercise with Stack.
9.
Create a file containing a function f( ) which takes an int argument and