Object-oriented programming differs from traditional procedural programming in that OOP emphasizes making decisions during runtime instead of during compile time. Runtime means while a program is running, and compile time means when the compiler is putting a program together. A runtime decision is like, when on vacation, choosing what sights to see depending on the weather and your mood at the moment, whereas a compile-time decision is more like adhering to a preset schedule, regardless of the conditions.

Runtime decisions provide the flexibility to adjust to current circumstances. For example, consider allocating memory for an array. The traditional way is to declare an array. To declare an array in C++, you have to commit yourself to a particular array size. Thus, the array size is set when the program is compiled; it is a compile-time decision. Perhaps you think an array of 20 elements is sufficient 80% of the time but that occasionally the program will need to handle 200 elements. To be safe, you use an array with 200 elements. This results in your program wasting memory most of the time it’s used. OOP tries to make a program more flexible by delaying such decisions until runtime. That way, after the program is running, you can tell it you need only 20 elements one time or that you need 205 elements another time.

In short, with OOP you would like to make the array size a runtime decision. To make this approach possible, the language has to allow you to create an array—or the equivalent—while the program runs. The C++ method, as you soon see, involves using the keyword new to request the correct amount of memory and using pointers to keep track of where the newly allocated memory is found.

Making runtime decisions is not unique to OOP. But C++ makes writing the code a bit more straightforward than does C.

The new strategy for handling stored data switches things around by treating the location as the named quantity and the value as a derived quantity. A special type of variable—the pointer—holds the address of a value. Thus, the name of the pointer represents the location. Applying the * operator, called the indirect value or the dereferencing operator, yields the value at the location. (Yes, this is the same * symbol used for multiplication; C++ uses the context to determine whether you mean multiplication or dereferencing.) Suppose, for example, that manly is a pointer. In that case, manly represents an address, and *manly represents the value at that address. The combination *manly becomes equivalent to an ordinary type int variable. Listing 4.15 demonstrates these ideas. It also shows how to declare a pointer.

Listing 4.15. pointer.cpp

// pointer.cpp -- our first pointer variable

#include

int main()

{

    using namespace std;

    int updates = 6;        // declare a variable

    int * p_updates;        // declare pointer to an int

    p_updates = &updates   // assign address of int to pointer

// express values two ways

    cout << "Values: updates = " << updates;

    cout << ", *p_updates = " << *p_updates << endl;

// express address two ways

    cout << "Addresses: &updates = " << &updates

    cout << ", p_updates = " << p_updates << endl;

// use pointer to change value

    *p_updates = *p_updates + 1;

    cout << "Now updates = " << updates << endl;

    return 0;

}

Here is the output from the program in Listing 4.15:

Values: updates = 6, *p_updates = 6

Addresses: &updates = 0x0065fd48, p_updates = 0x0065fd48

Now updates = 7

As you can see, the int variable updates and the pointer variable p_updates are just two sides of the same coin. The updates variable represents the value as primary and uses the & operator to get the address, whereas the p_updates variable represents the address as primary and uses the * operator to get the value (see Figure 4.8). Because p_updates points to updates, *p_updates and updates are completely equivalent. You can use *p_updates exactly as you would use a type int variable. As the program in Listing 4.15 shows, you can even assign values to *p_updates. Doing so changes the value of the pointed-to value, updates.

Figure 4.8. Two sides of a coin.

Declaring and Initializing Pointers

Let’s examine the process of declaring pointers. A computer needs to keep track of the type of value to which a pointer refers. For example, the address of a char typically looks the same as the address of a double, but char and double use different numbers of bytes and different internal formats for storing values. Therefore, a pointer declaration must specify what type of data to which the pointer points.

For example, the preceding example has this declaration:

int * p_updates;

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги