• No results found

1 #include <cstdlib> 2 #include <iostream> 3 4 using namespace std; 5 6 class my_object 7 { 8 public:

9 void SetI(int iValue); 10 int GetI();

11

12 void SetF(float fValue); 13 float GetF();

14

15 private: 16 int i;

17 float f; 18 }; 19 20

21 void my_object::SetI(int iValue) 22 { 23 i = iValue; 24 } 25 26 27 int my_object::GetI() 28 { 29 return (i); 30 } 31 32

33 void my_object::SetF(float fValue) 34 { 35 f = fValue; 36 } 37 38 39 float my_object::GetF() 40 { 41 return (f); 42 } 43 44

45 int main(int argc, char *argv[]) 46 {

47 my_object anObject, anotherObject; 48 49 anObject.SetI(10); 50 anObject.SetF(3.14159); 51 52 anotherObject.SetI(-10); 53 anotherObject.SetF(0.123456); 54

55 cout << "anObject.i = " << anObject.GetI() << endl; 56 cout << "anObject.f = " << anObject.GetF() << endl; 57

58 cout << "anotherObject.i = " << anotherObject.GetI() << endl; 59 cout << "anotherObject.f = " << anotherObject.GetF() << endl; 60

61 system("PAUSE"); 62 return (EXIT_SUCCESS); 63 }

The program in Listing 3.3 is a modification of the program in Listing 3.2. If you compare the two programs, you'll see some very important changes. First, the program in Listing 3.3 changed the member data from public to

private. You'll see this on lines 1517. Recall that any function in a program can access public member data. The same is true for public member functions.

and 17 can only be accessed by member functions. It's as if the class is a very exclusive club; only members can use the club's private goodies.

The list of member functions is shown on lines 913. Notice that all of these functions are public. This is typically how programmers define classes. You should only rarely make member data publicly accessible. Normally, the member functions should be public and the member data private.

The reason programmers make class data private and functions public is

simple: control. If a class's member data can only be accessed by the member functions, then we're controlling how the data can be changed. If the member functions never let the data get into an invalid state, then the data will always be valid.

Remember our dragon example we used when we first started talking about classes? Recall that the dragon in the game could eat fireberries to spit fire farther. Suppose the number of fireberries the dragon has eaten is stored in the dragon class as a data member. What would happen in the game if that

number somehow got to be negative? Oops. Now the dragon swallows fire rather than spits it. The game will probably crash. That's why it's vital to keep all data valid at all times.

Tip

Except in very rare circumstances, class data should be kept private. Usually, the member functions are public. Only the

member functions can access the private member data. Using this rule when defining classes goes a long way toward keeping the member data in a valid state at all times.

When we define objects, controlling the access to member data helps keep the data in a valid state. No functions outside the class can change private data. As long as the member functions never let the data become invalid, the data is always in a valid state. This is such an important point that I'm going to

emphasize it with a special Tip.

If you look back at Listing 3.3, you'll see the prototypes for the member functions on lines 913. Putting the prototypes in the class tells the compiler which functions are members. The member functions for this class are very simple: All they do is set or get the values of the member data. We'll see in

later chapters that member functions can also check the values before they set the member data.

The actual functions are given on lines 2142. Let's focus on the first line of the

SetI() function, which appears on line 21. Notice that the first line of the

function includes the name of the class followed by two colons. Two colons used together like thatknown as the C++ scope resolution operatoris a way to tell the compiler, "This is the function SetI() that I said was a member in the my_object class definition." The compiler replies, "Aha. So every time I see a call

to the my_object class's SetI() function, this is the function I'll use." All member

functions must be written in this way.

The SetI() function sets the value of i. You might be thinking, "Duh. I could tell

that from the name of the function." That's exactly why the function is named

SetI(). When you write your member functions, name them in a way that

anyone looking at your code can tell what the function does by its name. If you try to explain what the function does, "Duh" is a good response to getit means you named your function well.

Note

It is possible to write member functions a bit differently: as inline member functions. We discuss inline member functions later in this chapter. You'll see that even inline member functions can be

written the way the functions in Listing 3.3 are written. In fact, it is actually preferable to do so. Therefore, I recommend that you use the style shown here.

As I mentioned, the SetI() function sets the value of i to the value in the iValue

parameter. In most programs, the SetI() function would check the value of iValue

before saving it into i. I'll show how to do that sort of data validation when we

discuss if-else statements in "The if-else Statement" section later in this chapter.

Now take a look at the main() function in Listing 3.3. On lines 4950, you'll see

calls to the SetI() and SetF() functions. Notice that the program calls member

functions by stating the name of the object, followed by a period, and then the name of the function. There is an important reason for doing it this way: If you look on lines 5253, you'll see two more calls to the SetI() and SetF() functions.

The difference between these two pairs of function calls is that the first pair sets the member data in the anObject variable, while the second pair sets the

member data of the anotherObject variable. So any time you call a member

function, you call that function on an object. The function uses the member data of that particular object and no other. This enables you to specifically state which object you're changing.

Tip

Make every function name describe what the function does.

Lines 5559 demonstrate calls to the GetI() and GetF() functions. Again, they follow

the same pattern as calls to the SetI() and SetF() functions. Specifically, they state

the variable name, then a period, and then the function name. Your programs always call member functions in this way.