Home | Gaming | Programming | Play Online | Contact | Keyword Query
Games++ Games & Game Programming

GAMES++
Games++ Home
Games++ Gaming
Games++ Programming
Beta Testing Games
Free Online Games
Hints & Cheats

BROWSER UTILITIES
E-mail This Page
Add to Favorites

SITE SEARCH

Web Games++

AFFILIATES
Cheat Codes
Trickster Wiki
Game Ratings
Gameboy Cheats
PlayStation Cheats
BlackBerry Games
Photoshop Tutorials
Illustrator Tutorials
ImageReady Tutorials

ADVERTISEMENT

ADVERTISEMENT

Ch 10: Inheritance - C++ by Metrowerks

Introduction to C++ by Metrowerks

Inheritance, Base Class Access Control, and Protected Members

This lesson will introduce two important C++ attributes: inheritance and virtual functions. In C++, you can define an object based on another. When a class is derived from another, it inherits the attributes of the class it is derived from -- its base class. Virtual functions are those that have the same parameter list as those in parent and/or descendant functions, allowing for consistent responses within class hierarchies.

Through the use of inheritance, C++ allows for object-oriented programming. Inheritance allows the creation of hierarchical classifications. A general class can be created, and subordinate classes can be derived from the original classes. These classes maintain the original class' attributes and provide room for the addition of new attributes. Multiple classes can be derived from a single class!

Introduction to Inheritance

A class that passes on its attributes is called a base class. The class that inherits these attributes from the original class is called a derived class. A derived class can then serve as a base class for yet another class. With this process, a hierarchy of classes can be achieved.

Let's look at a sample class, transportation, which contains several data fields relating to modes of transportation. A second class, airtrans, is then derived from the original. This new class adds features relating only to air transportation, and a third class, groundtrans, will contain features pertaining solely to ground transportation:

class transportation {
    int passengers;
    int speed;
public:
    void set_passengers(int val) {passengers = val;}
    int get_passengers() {return passengers;}
    void set_speed(int val) {speed = val;}
    int get_speed() {return speed;}
};
enum plane_type {b47, b737, Prop};
class airtrans : public transportation {
    enum plane_type plane;
public:
    void set_plane_type(plane_type val) {plane = val;}
    int get_plane_type() {return plane;}
};
class groundtrans : public transportation {
    int wheels;
    int cargospace;
public:
    void set_wheels(int val) {wheels = val;}
    int get_wheels() {return wheels;}
    void set_cargospace(int val) {cargospace = val;}
    int get_cargospace() {return cargospace;}
};

Base Class Access Control

Each of the preceding derived classes has been declared using the public keyword. By default, the class specifier for a base class type is private. The base class access specifier must be either private, public, or protected.

With the use of the public specifier, all the public members of the base class remain public in the derived class. With a private declaration (or no declaration), the derived class inherits the public members of its base class, but they then become private members of the derived class. In both instances, the derived class has no access to the private members of the base class.

Using Protected Members

When a member of a class is declared as protected, that member is not accessible by non-member parts of the program. There is one exception to this rule: when a protected member of a class is inherited, it can then be accessed by members of the new, derived class, but may not be further passed down to future derived classes. :::C+Programming:::

Multiple Base Class Inheritance, Constructors, and Destructors

We will now look further at the concept of inheritance. Let's begin with a look at multiple base class inheritance. Then, we will look at how inheritance relates to constructor and destructor functions. Finally, we will look at passing parameters to base class constructors.

Inheriting Multiple Base Classes

A derived class can inherit attributes from more than one base class. The following program excerpt shows a derived class declaration that inherits attributes from two base classes: class1 and class2:

#include 
using namespace std;
class class1 {
protected:
    int x;
public:
    void showx() { cout << x << "\n"; }
};
class class2 {
protected:
    int y;
public:
    void showy() {cout << y << "\n"; }
};
// Inherit multiple base classes
class derived_class: public class1, public class2 {
public:
    void set(int i, int j) { x=i; y=j; }
};

The class derived_class will have the attributes of, and access to, members of both class1 and class2. The comma-separated list of class names and the use of an access specifier for each base class are the important items to remember when dealing with multiple inheritance.

Constructor and Destructor Functions

#include 
using namespace std;
class bclass {
public:
    bclass() {cout << "Base class constructor called.\n";}
    ~bclass() {cout << "Base class destructor called.\n";}
};
class dclass: public bclass {
public:
    dclass() {cout << "Derived class constructor called.\n";}
    ~dclass() {cout << "Derived class destructor called.\n";}
};
int main()
{
    dclass o1;
    return 0;
}

This program does nothing but invoke the constructor and destructor functions. The output of this program would be:

Base class constructor called.
Derived class constructor called.
Derived class destructor called.
Base class destructor called.

From this output, you can see that when an object is created, the first constructor function called is that of the base class. The constructor function of the derived class follows. When an object is destroyed, the order is reversed: the derived class destructor precedes that of the base class.

This order should make sense. The base class constructor establishes the characteristics of the base class object. Then, the derived class constructor adds those attributes to the derived class. Likewise, when an object is destroyed, the destructor function of the derived class does its work, then the destructor function of the base class object takes care of the rest.

In a hierarchical situation, when a derived class serves as the base class for a second derived class, the standard order of precedence will hold true. The first constructor called is that of the original base class, followed by its derived class, followed by the class derived from that class. Conversely, the destructor functions will start on the "inside" and work their way out.

If a program contains multiple base classes, the base class immediately after the : has its constructor called first. Then, the program continues through the base classes, from left to right, before calling any constructor function of a derived class. When the destructor functions are called, the destructor of the last derived class is called first. The destructor functions then move from right to left, clearing derived classes first. Then, the base classes are cleared in inverse order of construction.

Passing Parameters to Base Class Constructors

Another question arises when dealing with multiple inheritance: how does one pass parameters to the constructor function of a base class? The following program is a modified version of the previous program:

#include 
using namespace std;
class bclass {
protected:
    int j;
public:
    bclass(int y) 
        {j = y; cout << "Base class constructor called.\n";}
    ~bclass() {cout << "Base class destructor called.\n";}
};
class dclass: public bclass {
    int k;    
public:
    // dclass uses x; y is passed along to bclass
    dclass(int x, int y): bclass(y) 
        {k = x; cout << "Derived class constructor called.\n";}
    ~dclass() {cout << "Derived class destructor called.\n";}
};
int main()
{
    dclass o1(5,6);
    return 0;
}

The output from this program is the same as in the previous example:

Base class constructor called.
Derived class constructor called.
Derived class destructor called.
Base class destructor called.

In this program, however, some values were assigned. After both constructors are called, x has the value of 5 and y has the value of 6. Review this program to see how it was set up to pass arguments to the constructor functions of both the derived class and base class. Pay particular attention to the line:

dclass(int x, int y): bclass(y)

You should notice that in the class declaration, the base class, bclass, requires the parameter int y. Since two parameters are used in dclass(), you ensure that the base class is passed the necessary parameters by using the declaration (assuming that parameter2 is the base class argument):

derived_class(type parameter1, type parameter2, . . .): base_class(parameter2)
{
    // body of derived constructor
}

Access Granting and Virtual Base Classes

When the characteristics of any member of a base class are inherited by members of a derived class (whether they be private, protected, or public members), these new members become private members within the derived class. We will now discuss the ways to grant different access levels to members of a derived class. After that, we will begin our discussion of virtual functions by looking at virtual base classes.

Granting Access

This section may seem a little unusual. Pay close attention; I'm sure you'll understand by the time we get to the end of this section. There are two ways to change the access level of inherited members of a derived class. The first method is a recent development in the world of C++, and it has become the new standard. This new standard is the using declaration. However, we will postpone our study of the using declaration until we begin our discussion of namespaces. The second way to change an access level is to use access declarations. This method was once the standard for C++, and it will still be seen in older programs. Because you may still encounter access declarations, we will discuss them here. However, for new programs, the using method should be used.

The following base and derived class declarations show how access declarations work:

class bclass {
public:
    int a;
};
class dclass: private bclass {
public:
    bclass::a;
};

Even though, by default, a is inherited by dclass as private, the access declaration

bclass::a;

changes a's level of access to public.

Virtual Base Classes

Think about the following situation: a class named bclass is declared. Then, two classes are derived from that original: dclass1 and dclass2. Next, yet another new class is declared -- a derivative of both dclass1 and dclass2 -- dclass3. Looking at this situation, if a variable from the original class, bclass, is called in association with dclass3, what will happen?

There are essentially two copies of bclass in dclass3: the one inherited from dclass1, and the one inherited from dclass2. If dclass3 tries to reference a variable in bclass, an error will occur. To prevent an extra copy of bclass from being created during the declaration of dclass3, we use virtual base classes.

The following class declarations clarify the situation described above. Notice the use of the keyword virtual in the declaration of the derived classes:

class bclass {
public:
    int a;
};
class dclass1: virtual public bclass {
public:
    int b;
};
class dclass2: virtual public bclass {
public:
    int c;
};
class dclass3: public dclass1, public dclass2 {
public:
    int d;
};

There is only one difference between a virtual class and a "normal" class. If a virtual base class is inherited more than once by the same class, only one copy of it will be present. If a "normal" class is inherited more than once by the same class, multiple copies of it will be present in the derived class.

Next Lesson

Copyright © 1998-2007, Games++ All rights reserved. | Privacy Policy