ÄúµÄλÖãºÑ°ÃÎÍøÊ×Ò³£¾±à³ÌÀÖÔ°£¾C/C++±à³Ì£¾Tutorial of C++

C++ Programming Tutorial IV

Inheritance


class derived_class_name:access_specifier base_class_name {
    // body of class
};


  • Inheritance allows hierarchical classifications.

  • A class that is inherited is referred to as a base class.

  • The class that does the inheriting is called the derived class.

  • The class_specifier can be public, private, or protected.

  • A derived class can be used as a base class for another derived class (multiple inheritance).

  • Recall a class declaration:
        class class_name {
            private data and functions
        access-specifier:
            data and functions
        access-specifier:
            data and functions
        ...
        ...
        access-specifier:
            data and functions
        
        } object-list;
        



Base Class Access Control, Public


#include  <iostream.h>

class base {
    int i, j;
public:
    void set(int a, int b) {i=a; j=b;}
    void show() {cout << i << " " << j << "\n";}
};

class derived : public base {
    int k;
public:
    derived(int x) {k=x;}
    void showk() {cout << k << "\n";}
};

main()
{
    derived ob(3);

    ob.set(1, 2);    // access member of base
    ob.show();    // access member of base

    ob.showk();    // uses member of derived class

    return 0;
}


  • When the access specifier for a base class is public, all public members of the base become public members of the derived class; and

  • All protected members of the base become protected members of the derived class.

  • The base class' private elements remain private to the base and are not accessible by members of the derived class.



Base Class Access Control, private


// This program won't compile.
#include  <iostream.h>

class base {
    int i, j;
public:
    void set(int a, int b) {i=a; j=b;}
    void show() {cout << i << " " << j << "\n";}
};


// Public elements of base are private in derived.
class derived : private base {
    int k;
public:
    derived(int x) {k=x;}
    void showk() {cout << k << "\n";}
};

main()
{
    derived ob(3);

    ob.set(1, 2);    // error, can't access set()
    ob.show();    // error, can't access show()

    return 0;
}


  • When the base class is inherited by using the private access-specifier, all public and protected members of the base class become private members of the derived class.

  • This means that they are still accessible by members of the derived class but cannot be accessed by parts of your program that are not members of either the base or derived class.



Protected Class Members


class base {
protected:
    int i, j;    // private to base, but accessible by derived
public:
    void set(int a, int b) {i=a; j=b;}
    void show() {cout << i << " " << j << "\n";}
};


  • When a class member is declared as protected, that member is not accessible by other, non-member elements of the program just like private members.



Inheriting Protected Members, public


#include <iostream.h> 

class base {
protected:
        int i, j;       // private to base, but accessible by derived
public:
        void set(int a, int b) {i=a; j=b;}
        void show() {cout << i << " " << j << "\n";}
};


class derived : public base {
    int k;
public:
    // derived may access base's i and j
    void setk() {k=i*j;}

    void showk() {cout << k << "\n";}
};


main()
{
    derived ob;

    ob.set(2, 3);    // OK, known to derived
    ob.show();     // OK, know to derived

    ob.setk();
    ob.showk();
    return 0;
}


  • If the base class is inherited as public, then the base class' protected members become protected members of the derived class and are, therefore, accessible by the derived class.



Inheriting Protected Members, protected


#include <iostream.h> 

class base {
protected:
        int i, j;       // private to base, but accessible by derived
public:
        void setij(int a, int b) {i=a; j=b;}
        void showij() {cout << i << " " << j << "\n";}
};


// Inherit base as protected.
class derived : protected base {
    int k;
public:
    // derived may access base's i and j and setij().
    void setk() {
        setij(10, 12); 
        k = i*j;
    }

    void showall() {
        cout << k << " ";
        showij();
    }
};


main()
{
    derived ob;

// ob.setij(2, 3);    // illegal, setij() is protected member of derived

    ob.setk();    // OK, public member of derived
    ob.showall();    // OK, public member of derived

// ob.showij();        // illegal, showij() is protected member of derived

    return 0;
}


  • When the base class is inherited as protected, all public and protected members of the base class become protected members of the derived class.



Inheriting Multiple Base Classes


#include <iostream.h> 

class base1 {
protected:
    int x;
public:
    void showx() {cout << x << "\n";}
};


class base2 {
protected:
    int y;
public:
    void showy() {cout << y << "\n";}
};


// Inherit multiple base classes.
class derived : public base1, public base2 {
public:
    void set(int i, int j) {x=i; y=j;}
};


main()
{
    derived ob;

    ob.set(10, 20);        // provided by derived 
    ob.showx();        // from base 1
    ob.showy();        // from base 2

    return 0;
}


  • To inherit more than one base class, use a common-separated list.

  • Be sure to use an access specifier for each base inherited.



Summary of Inheritance Access Control


Inheritance Control, (Derived class)
public private protected
Access Control, (Base Class) public public private protected
private Not accessible Not accessible Not accessible
protected protected private protected


Inheritance - When Constructors and Destructors are Executed?


#include <iostream.h> 

class base {
public:
    base() {cout << "Constructing base\n";}
    ~base() {cout << "Destructing base\n";}
};


class derived1 : public base {
public:
    derived1() {cout << "Constructing derived1\n";}
    ~derived1() {cout << "Destructing derived1\n";}
};

    
class derived2 : public base {
public:
    derived2() {cout << "Constructing derived2\n";}
    ~derived2() {cout << "Destructing derived2\n";}
};


main()
{
    derived2 ob;

    // construct and destruct ob

    return 0;
}
Output:
Constructing base
Constructing derived1
Constructing derived2
Destructing derived2
Destructing derived1
Destructing base


  • When an object of a derived class is created, if the base class contains a constructor, it will be called first, followed by the derived class' constructor.

  • When a derived object is destroyed, its destructor is called first, followed by the base class' destructor, if it exists.

  • Put differently, constructor functions are executed in their order of derivation.

  • Destructor functions are executed in reverse order of derivation.

  • In case of multiple inheritance, the general rule applies:
    Constructors are called in order of derivation, destructors in reverse order.



Passing Parameters to Base Class Constructors?


#include <iostream.h> 

class base {
protected:
    int i;
public:
    base(int x) {
        i=x; 
        cout << "Constructing base\n";
    }

    ~base() {cout << "Destructing base\n";}
};


class derived:public base {
    int j;
public:
    // derived uses x; y is passed along to base.
    derived(int x, int y): base(y) {
        j=x;
        cout << "Constructing derived\n";
    }

    ~derived() {cout << "Destructing derived\n";}

    void show() {cout << i << " " << j << "\n";}
};


main()
{
    derived ob(3, 4);

    ob.show();    // displays 4 3
    
    return 0;
}
Output:

derived-constructor(arg-list): base1(arg-list),
                               base2(arg-list),
                               ...
                               ...
                               baseN(arg-list)
{
    // body of derived constructor
}


  • Use an expanded form of the derived class' constructor declaration that passes along arguments to one or more base class constructors.

  • Even if a derived class' constructor does not use any arguments, it will still need to declare one or more if the base class takes one or more arguments.

  • An argument that is passed along to a base class does not preclude its use by the derived class as well.


End of Tutorial IV


 

[ tutorial 1(a)| tutorial 1(b)| tutorial 2| tutorial 3| tutorial 4]