3.1 DEFINING A CLASS IN C


3.1 DEFINING A CLASS IN C++

Here is a simple example of a C++ class:

      class User {           string name;           int age;      }; 

We have defined the class User with two variables, name and age. As mentioned before, these are usually referred to as members, data members, or fields. The former is of type string and the latter of type int. Note that a C++ class needs a semicolon at the end to terminate the definition.

The reader who is not already familiar with the system-supplied classes in C++ is probably perplexed by the type string. An introduction to the C++ string type will be provided in the next chapter. All we want to say here is that while in C a string of characters is represented by a null-terminated array of char's, as in

      char str[] = "hello"; 

or by a pointer to type char, as in

      char* str = "hello"; 

where the right hand side is a string literal, it is more common in C++ to use the string type. Of course, one also has the option of using the C-style strings in C++, but these don't come with the same protections as the string type, as we will see in the next chapter.

A class defines a new type. It may be system supplied, or can be programmer defined. With the User class defined as above, we are allowed to declare variables of type User. For example, we could declare the name u to be a variable of type User by

      User u; 

just as you might declare the name i to be a variable of type int by

      int i; 

or the name ch to be a variable of type char by

      char ch; 

One is immediately faced with the following question for a user-defined class: How does one initialize variables of such types? How would one initialize the variable u for a User whose name is "Zaphod" and whose age is 119? What we really want to do is to create a specific object of type User whose name member is set to Zaphod and whose age member is set to 119. An object is constructed by instantiating a class with the help of a class constructor. A constructor sets aside a part of the memory for the object that one wants to create and sets the various members of the object according to the arguments supplied to the constructor. If the arguments for some or all of the data members are not supplied, the constructor may use default values.

Here is a more useful definition of the User class with a constructor included:

      class User {           string name;           int age;      public:           User( string str, int yy ) { name = str; age = yy; }      }; 

The use of the keyword public as shown places the constructor in the public section of the class. (The data members name and age are implicitly in the private section of the class.) This, as further explained in Section 3.11, allows the rest of your program to create objects of type User. Also note that there is no return type specified for the constructor. That's because a constructor is really not a function; its job is to appropriate the memory needed and build an object therein.

Now that we have available to us a constructor for the class User, we can create objects of this type by invoking one of the following forms in C++

      User u( "Zaphod", 119 );                        //(A)      User* p = new User( "Zaphod", 119 );            //(B) 

The constructor invocation in line (A), in the form of a declaration/initialization for the variable u, allocates memory for the new object on the stack. This memory gets freed up automatically when the variable u goes out of scope. In the constructor invocation in line (B), the operator new allocates fresh memory for the object on the heap and then returns a pointer to this memory. This memory can only be freed up under program control by explicit invocation of the delete operator, as in line (C) below:

      User* p = new User( "Zaphod", 119 );      delete p;                                      //(C) 

When invoked on a pointer to a class-type object, the delete operator invokes the class's destructor. We will have more to say about destructors in Section 3.8 of this chapter and in Chapter 11.

Since we would also want to see the objects we create, let's include in the class definition a print function:

      class User {           string name;           int age;      public:           User( string str, int yy ) { name = str; age = yy; }           void print() {                                              //(D)                cout << "name:" << name << " age: " << age << endl;    //(E)           }      }; 

In Section 2.1 of the previous chapter, we briefly discussed the purpose served by the insertion operator ‘<<' and by the output stream object cout used in line (E).

A member function, such as print() in line (D) above, is invoked on a specific object. The syntax of this invocation depends on whether the function is invoked directly on an object or on a pointer to an object, as shown in the following two examples:

      User u( "Zaphod", 119 );      u.print();              // name: Zaphod age: 119                       //(F)      User* p = new User( "Zaphod", 119 );      p->print();            // name: Zaphod age: 119                       //(G) 

where ‘.' in line (F) and ‘->' in line (G) are known as the member access operators.

Here is a working C++ program that uses the class definition provided above:

 
//User1.cc #include <iostream> #include <string> using namespace std; class User { string name; int age; public: User( string str, int yy ) { name = str; age = yy; } void print() { cout << "name: " << name << " age: " << age << endl; } }; int main() { User u( "Zaphod", 119 ); u.print(); return 0; }

C++ allows the implementation code for a class to reside outside the definition of the class itself. Shown below is the same program as above, but with the constructor and the print function definition outside the class definition:

 
//User2.cc #include <iostream> #include <string> using namespace std; class User { string name; int age; public: User( string str, int yy ); //(H) void print(); //(I) }; User::User( string str, int yy ) { //(J) name = str; age = yy; } void User::print() { //(K) cout << "name: " << name << " age: " << age << endl; } int main() { User u( "Zaphod", 119 ); u.print(); return 0; }

So whereas the constructor is declared in line (H) inside the class definition, the implementation code for the constructor is provided in line (J) outside the class. Same for the print function; the declaration as a member function is in line (I) and the definition at line (K). Note the use of the scope operator '::' in lines (J) and (K) to help the compiler figure out that the definitions being provided are for the class User. This usage of the scope operator is as a class scope operator.[3] As we will explain in Chapter 11, one has no choice but to resort to the class scope operator in the manner shown and provide definitions external to a class when classes are interleaved in a C++ program. This is necessitated by the fact that, unlike what happens in Java compilation, a C++ compiler does not possess a look-ahead capability.

There is yet another variation on how a class is defined in C++. This variation concerns how the data members of a class instance are initialized by a constructor. The program shown below is identical to the program User1.cc, except that in line (L) below the constructor now uses the member initialization syntax for the initialization of the data members of an object. Strictly speaking, as will be explained in Chapter 7, it is necessary for only the const and the reference data members of a class to be initialized in this manner. But it is common to see code in which this sort of initialization is carried out for other types of data members also.

 
//User3.cc #include <iostream> #include <string> using namespace std; class User { string name; int age; public: User( string str, int yy ) : name( str ), age( yy ) {} //(L) void print() { cout << "name: " << name << " age: " << age << endl; } }; int main() { User u( "Zaphod", 119 ); u.print(); return 0; }

Please refer back to the previous chapter on how to compile and run the working programs shown in this section.

[3]A C++ class member function whose implementation code is provided inside the class definition is considered to be an inline function. Whether or not a function is inline can affect a compiler's ability to perform certain types of optimizations. A member function defined outside a class can also be made inline through explicit declaration. See Section 9.5 of Chapter 9 for details.




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net