0664-0666

Previous Table of Contents Next

Page 664

Listing 26.12 provides a simple example of an object in C++ with a single constructor and a single destructor. Note that in C++ the constructor has the same name as the class and returns a pointer to an instance of an object belonging to the class. Although the arguments to the constructor can be redefined, the return type cannot be. If no constructor is specified, the compiler creates a default constructor that simply allocates memory for the new instance and loads it. Similar rules apply to the destructor, which always has the name of the class preceded by a tilde and returns void (nothing). In Listing 26.12, the destructor is named ~Car().

Listing 26.12. A simple class, with a constructor and destructor as the only member functions.

 class Car {     public:         char      *Make;         char      *Model;         unsigned  Year;         Car(char* CarMake, char* CarModel, unsigned CarYear);         ~Car(); }; Car::Car(char* CarMake, char* CarModel, unsigned CarYear) {     Make = strdup(CarMake);     Model = strdup(CarModel);     Year = CarYear; } Car::~Car() {     free(Make);     free(Model); 
NOTE
The free statements in the destructor are very important. When the class is instantiated , additional memory is allocated for these data members . Placing the free statements in the destructor is the best way to eliminate potential memory leaks.

To create an instance of Car, declare a pointer to Car, which receives the return value of the constructor:

 Car *MyCar; MyCar = new Car("Ford", "Mustang", 1967); // To destroy the object, use the delete operator: delete MyCar; 

This simple example illustrates the encapsulation of data and methods in an object and the instantiation and destruction of an instance of the object. These concepts are the very foundation of object-oriented programming techniques.

Page 665

Information hiding is a form of encapsulation in which data elements or methods can be accessed only by the methods of the object. This point was illustrated in the context of Oracle packages in several ways. In Listing 26.6, the user who last updated a record and the timestamp indicating when the record was last updated were inserted by a function without any intervention by the user or the calling application. Tables, functions, procedures, and other database objects can also be hidden by Oracle packages as illustrated in Listing 26.9. In general, variables and constructs declared in the package specification are visible, or public. Variables and constructs declared within the package only are hidden, or private.

In C++, variables and functions can be declared as public, private, or protected in the class definition. Public constructs can be accessed anywhere in a program, whereas private and protected data and methods can be accessed only through member functions and member functions of friend classes. These subjects are discussed in greater detail in the explanation of Listing 26.14. At this point, it is only important to recognize that this is how C++ hides information. For example, if the Car class from Listing 26.12 were redefined as shown in Listing 26.13, the Mileage data member could only be accessed by the constructor and the member functions GetMileage and IncrementMileage.

Listing 26.13. A redefinition of the Car class illustrating the use of the protected keyword.

 class Car {     public:         char      *Make;         char      *Model;         unsigned  Year;        Car(char* CarMake, char* CarModel, unsigned CarYear            ,unsigned long Mileage);         ~Car();         unsigned long GetMileage();         void IncrementMileage(unsigned Miles);     protected:         unsigned long Mileage; 

};

If this were the extent of the implementation of the Car class, Mileage could only be increased using methods of the Car class, namely IncrementMileage(). If Mileage was declared as public, however, it could be modified by any external code using an assignment, such as

MyCar->Mileage = 10;

You can also use protected data and functions to abstract implementation details, such as database transactions. The SQL used to insert a car could be declared protected, parameterized, and initialized when an instance is constructed . The application could then add a car to the database by accessing a public member function without knowing the SQL syntax or that it even exists.

Page 666

An extremely important feature of the object-oriented model is the concept of inheritance. Inheritance defines a class hierarchy in which a descendent class receives the member functions and data elements of the parent class to which it belongs. For example, you can create a base class without any intention of constructing the object. Base classes are often created only to be inherited from. Listing 26.14 illustrates this point in the context of the simple example of the Car class.

Listing 26.14. The concept of inheritance.

 class Vehicle {     public:         char      *Make;         char      *Model;         unsigned  Year; }; class Car : public Vehicle {     public:         Car(char* CarMake, char* CarModel, unsigned CarYear            ,unsigned long Mileage);         ~Car();         unsigned long GetMileage();         void IncrementMileage(unsigned Miles);     protected:         unsigned long Mileage; 

};

Note that the base class Vehicle enables the compiler to generate the default constructor and destructor and that it now contains the public data members. They still exist in the Car class because they are inherited from Vehicle. The keywords private and protected are important to the behavior of inheritance. Although protected member functions can be accessed by derived classes, private members cannot be. A friend class can access both private and protected members. friend classes do not inherit from the base class but have full access rights to member functions of the base class.

The virtual keyword is also important to inheritance. Class functions declared as virtual can be redefined by descendants without changing the call interface (overloading the function). If the function is redefined in the descendant with different arguments or return types, the virtual keyword is ignored, and the function is, in effect, overloaded.

Base classes commonly contain virtual functions with the intention of enabling descendants to override them rather than overload them. Although descendants can override base class functions without the virtual keyword, you can use virtual functions to force descendants to redefine functions. A virtual function typically has a void return type and no arguments. Listing 26.15 is an example of a base class with virtual functions and two derived classes that override the virtual functions, or redeclare them.

Previous Table of Contents Next


Oracle Unleashed
Oracle Development Unleashed (3rd Edition)
ISBN: 0672315750
EAN: 2147483647
Year: 1997
Pages: 391

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