Member functions and InterfacesInput stream, member functions (methods), return values, interfaces, functions returning void. So far we have been constructing and destroying objects. What else can we do to an object? We can't access its private data members, because the compiler wouldn't let us (not to mention that I haven't even talked about the syntax one would use to do it). It turns out that only the object itself (as specified in its class definition) can make a decision to expose some of its behavior and/or contents. Behavior is exposed via member functions, also called methods. If a member function is public, anybody can call it (we'll see the syntax in a moment). Our first member function is called GetValue. It returns an int. From the implementation of this function we can see that the returned value is that of the private data member _num. Now we know what it means to have access to an object; it means to be able to invoke its member functions. Here, the object num of the type InputNum is defined in the scope of main and that's where we can access it. And access we do, calling num.GetValue(). To put it in different words, we invoke the method GetValue() on the object num. Or, we are getting the value of object num. In still other words (Smalltalk-speak) we send the message GetValue to the object num. What we are getting back is an int, which we print immediately using our old friend std::cout. | |||||||
Download the Input series of sources
![]() source |
A few words of syntax clarification are in order. The type of the return value is always specified in front of the member function definition (or declaration, as will be explained later). A method that is supposed to return something must have a return statement at the end (later we'll see that a return from the middle is possible, too). If a function is not supposed to return anything, its return type is void. In all our previous examples main wasn't returning anything, so it was declared void. Not this time though. It turns out that main can return an integer. In fact it always returns an integer, even if it is defined as returning void (in that case it returns a more or less random number). By convention, main is supposed to return 0 if the program was successful. Otherwise it is supposed to return an error level. You can check for the error level after you've run your program from a batch file using the statement similar to this:
The keyword const following the declaration of a method, as in
Moreover, only methods declared const may be called on a const object. So far we've seen a const object _matter inside World. If Matter had a const method, like GetValue, it would have been okay to call it in the context of the object _matter (that is: _matter.GetValue() would compile all right). We'll see examples of that later. By the way, _num cannot be declared const any more, since it is not initialized in the preamble. The code in the body of the constructor is changing the (undefined) value of _num. Try compiling this program with a const _num and you'll see what happens. When the object num of class InputNum is constructed in main, it prompts the user to input a number. It then waits for a number and stores it in its private data member _num. This is done through the services of the input object std::cin. Std::cin gets input from the keyboard and stores it in a variable. Depending on the type of the variable, std::cin expects different things from the keyboard. For instance, if you call it with an int, it expects an integer; if you call it with a double, it expects a floating point number, etc. The set of public methods is called the interface and it defines the way clients may interact with the object. InputNum, for instance, provides read-only access to its contents. Because of that, we are guaranteed that the value of InputNum will never change once it is created. Successive calls to GetValue() will always return the same value. If it makes sense, it is also possible for an object to grant write access to its contents--for example, in our case, by defining the method
Then, after the call
To summarize, the set of public member functions defines the interface to the object of a given class. What is even more important, a well designed and well implemented object is able to fulfill a well defined contract. Programming in C++ is about writing contracts and fulfilling them. An interface can, and should, be designed in such a way that the client's part of the contract is simple and well defined. The object may even be able to protect itself from sloppy clients who break their part of the contract. We'll talk about it when we discuss the use of assertions. |