Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

C++ Inheritance

2.67/5 (2 votes)
25 Nov 2013CPOL5 min read 19.5K  
This article describes basic concepts of C++ Inheritance mechanism.

Introduction

This article describes basic concepts of C++ Inheritance mechanism. 

Inheritance

  • Inheritance is a mechanism of reusing and extending existing classes without modifying them, thus producing hierarchical relationships between them.
  • Inheritance is implemented in C++ through the mechanism of derivation. Derivation allows you to derive a class, called a derived class, from another class, called a base classes
  • The class whose members you want to include in your new class is called a base class. Your new class is derived from the base class.
  • You can also add new data members and member functions to the derived class.
  • When you derive a class, the derived class inherits class members of the base class. You can refer to inherited members (base class members) as if they were members of the derived classes
  • C++
    class A{ //A is the base class
    };
    class B: public A {
    int a; //we can add new data members
    void f(); //we can add new member function
    }; //B is the derived class
  • You can modify the implementation of existing member functions or data by overriding base class member functions or data in the newly derived class. If a member of a derived class has the same name as a base class, the base class name is hidden in the derived class.
  • C++
    class A{ //A is the base class
    };
    class B: public A {
    int a; //we can add new data members
    void f(); //we can add new member function
    }; //B is the derived class
  • You may derive classes from other derived classes, thereby creating another level of inheritance. The number of levels of inheritance is only limited by resources.
  • C++
    class A{ //A is the base class
    };
    class B: public A {
    int a; //we can add new data members
    void f(); //we can add new member function
    }; //B is the derived class
  • The new class contains a subobject of the type of the base classes

    Multiple Inheritance

  • Multiple inheritance allows you to create a derived class that inherits properties from more than one base classes
  • C++
    class A{ //A is the base class
    };
    class B: public A {
    int a; //we can add new data members
    void f(); //we can add new member function
    }; //B is the derived class
  • Because a derived class inherits members from all its base classes, ambiguities can result
  • C++
    class A{ //A is the base class
    };
    class B: public A {
    int a; //we can add new data members
    void f(); //we can add new member function
    }; //B is the derived class

    Image 1

  • In case of ambiguous data members a solution would be to override the base class members
  • C++
    class A{
    public:
    int a; //ambiguous member
    A():a(10){};
    };
    class B{
    public:
    int a; //ambiguous members 
    B():a(20){};
    };
    class C:public A,public B
    {
    public:
    int a; //overriding ambigous data members
    };
  • We can still access the override members of the base class using scope resolution operator
  • C++
    ;
    };
    class Derived:public Base
    {
    public:
    int a; //overriding ambigous data members
    Derived():a(100){};
    };
    int main()
    {
    Derived c1;
    cerr << c1.a << ":"<< endl; //accessing derived class member
    cerr << c1.Base::a << ":"<< endl; //accessing the base class member
    }
  • A direct base class cannot appear in the base list of a derived class more than once:
  • C++
    ;
    };
    class Derived:public Base
    {
    public:
    int a; //overriding ambigous data members
    Derived():a(100){};
    };
    int main()
    {
    Derived c1;
    cerr << c1.a << ":"<< endl; //accessing derived class member
    cerr << c1.Base::a << ":"<< endl; //accessing the base class member
    }

    Image 2

  • A derived class can inherit an indirect base class more than once.However this may result in ambiguities since it can be considered that 2 subobjects of Parent class exist which are both accessible throught the derived class.
  • C++
    class Parent{
    public:
    int a;
    }
    
    class Base:public Parent{
    public:
    void disp(){cout << a << endl;}
    };
    
    //both base and base1 have the same base class
    class Base1:public Parent{
    public:
    void disp(){cout << a << endl;}
    };
    
    
    class Derived:private Base,private Base1
     //this will cause error
    {
    public:
    };
    int main()
    {
    Derived d;
    d.disp();
    }

    Virtual Base Class

  • A derived can have virtual and non virtual base classes
  • If a derived classes ,inherits from same base class via multiple inheritance, it will have 2 subobjects of the base class leading to ambiguity, hence the virtual base class keyword can be used to specify that derived object contain only one copy of the inherited base class.
  • C++
    using namespace std;
    class Parent{
    public:
    int a;
    }
    //virtual base class
    class Base:public virtual Parent{
    public:
    void disp(){cout << a << endl;}
    };
    //virtual base class
    class Base1:public virtual Parent{
    public:
    void disp(){cout << a << endl;}
    };
    //not an error due to one subobject of indirect base class
    class Derived:private Base,private Base1 
    {
    public:
    };
  • In an inheritance containing virtual base classes, a name of class member that can be reached through more than one path of inheritance is accessed through the path that gives the most access.
  • C++
    class Parent{
    public:
    int a;
    }
    
    class Base:public virtual Parent{
    public:
    void disp(){cout << a << endl;}
    };
    
    class Base1:private virtual Parent{
    public:
    void disp(){cout << a << endl;}
    };
    
    //Base provides more access
    class Derived:private Base,private Base1
    {
    public:
    };
    int main()
    {
    Derived d;
    //It choose base,else this line woul
    //give error due to private inheritance
    cout << d.a <<endl; //take from Base
    }

    Ambiguous base classes

  • The order of derivation is relevant only to determine the order of default initialization by constructors and cleanup by destructors.
  • Using Keyword Declaration

  • A member function in the derived class will hide all other members with same name in the base class regardless of type of arguments or return type
  • C++
    class Base{
    private:
    int a; 
    public:
    void disp(){cout << a << endl;}//member disp will be hidden
    Base():a(10){};
    };
    class Derived:protected Base
    {
    public:
    void disp(int a){};//member named disp in derived class
    };
    int main()
    {
    Derived d;
    d.disp(); //this will give error since disp function is hidden
    }

    Image 3

  • A using declaration in a definition of a class A allows you to introduce a name of a data member or member function from a base class of A into the scope of A
  • C++
    class Base{
    private:
    int a; 
    public:
    void disp(){cout << a << endl;}
    Base():a(10){};
    };
    class Derived:protected Base
    {
    public:
    //introducing disp function from base to derived class
    using Base::disp; 
    void disp(int a){};
    };
    int main()
    {
    Derived d;
    d.disp();//because of using declaration this is allowed
    //name disp is overloaded with 2 functions 
    }
  • If the function with same names as that of base class declared with using keyword is present in the derived class the function in base class will be hidden and no conflict arises.
  • C++
    class Base{
    private:
    int a; 
    public:
    void disp(){cout << a << endl;} //function in case class
    Base():a(10){};
    };
    class Derived:protected Base
    {
    public:
    using Base::disp; //using keyword
    //function with same name,return type and args in derived class
    void disp(){cerr << "DErived" << endl;}; 
    void disp(int a){}; 
    };
    int main()
    {
    Derived d;
    d.disp();//will print derived ,no conflicts
    }
  • Using Declaration cannot resolve ambiguities due to same inherited members
  • C++
    class Parent{
    public:
    int a;
    };
    
    class Base:public Parent{
    using Parent::a;
    public:
    void disp(){cout << a << endl;}
    };
    
    class Base1:public Parent{};
    
    class Derived:public Base,public Base1{
    public:
    using Parent::a;
    void disp(){}; //a is not used hence no error in compilation
    };
  • The declaration of a member with an ambiguous name in a derived class is not an error. The ambiguity is only flagged as an error if you use the ambiguous member name.
  • C++
    class Parent{
    public:
    int a;
    };
    
    class Base:public Parent{
    using Parent::a;
    public:
    void disp(){cout << a << endl;}
    };
    
    class Base1:public Parent{};
    
    class Derived:public Base,public Base1{
    public:
    using Parent::a;
    void disp(){}; //a is not used hence no error in compilation
    };

    Pointer Derived Class and Base Class

  • Pointer to a Derived class can be converted to pointer of the base class
  • C++
    class Base{
    public:
    int a; 
    Base():a(10){};
    };
    class Derived:public Base
    {
    public:
    int a; //overriding ambigous data members
    Derived():a(100){};
    };
    int main()
    {
    Derived d1;
    Derived *d2=&d1; //
    Base *b1; 
    b1=d2; //convers pointer to base class from derived class
    cerr << b1->a << endl;//prints 10 of base class
    cerr << d2->a << endl;//prints 100 of derived class
    }
  • A pointer to base class cannot be derived to case class.
  • C++
    //In the above example,chaning the main function
    int main()
    {
    Derived d1;
    Derived *d2=&d1; //
    Base *b1; 
    d2=b1; //this line will give an error
    }
  • Members and friends of a class can implicitly convert a pointer to an object of that class to a pointer to either protected or public direct or indirect base class and direct private base class.
  • A direct base class is a base class that appears directly as a base specifier in the declaration of its derived class. An indirect base class is a base class that does not appear directly in the declaration of the derived class but is available to the derived class through one of its base classes For a given class, all base classes that are not direct base classes are indirect base classes. The following example demonstrates direct and indirect base classes
  • Classes that are declared but not defined are not allowed in base lists.

    Inherited member access

  • while inheriting the members from base class,we can hide some information of the base class.This can be done by specifying the access specifier.
  • An access specifier can be public, private, or protected.
  • In a public base class access the public and protected members of the base class remain public and protected members of the derived class respectively.
  • In a protected base class access the public and protected members of the base class are protected members of the derived class.
  • In a private base class access the public and protected members of the base class become the private members of the derived class.
  • The private members of the base class remain private members of derived classes
  • Private members of the base class cannot be used by the derived class unless friend declarations within the base class explicitly grant access to them.
  • The default access specifier is private

    Increasing Access

  • Suppose class B is a direct base class of class A. To restrict access of class B to the members of class A, derive B from A using either the access specifiers protected or private.
  • To increase the access of a member x of class A inherited from class B, use a using declaration. You cannot restrict the access to x with a using declarations
  • Access can be increased to member inherited as private or declared/inherited as protected
  • C++
    class Base{
    private:
    int a; 
    public:
    void disp(){cout << a << endl;}
    Base():a(10){};
    };
    class Derived:private Base
    {
    public:
    //disp is inherited as private but access increase by using declaration
    //in public access scope
    using Base::disp;
    
    };
    int main()
    {
    Derived d;
    d.disp();//without using declaration will give error
    }
  • Access to members declared as private in the base class cannot be increased
  • C++
    class Base{
    private:
    int a; 
    public:
    void disp(){cout << a << endl;}
    Base():a(10){};
    };
    class Derived:public Base
    {
    public:
    using Base::a; //this line will give error
    };
  • Access to a member cannot be reduced with a using declaration
  • C++
    class Base{
    private:
    int a; 
    public:
    void disp(){cout << a << endl;}
    Base():a(10){};
    };
    class Derived:public Base
    {
    private: //this will give an error
    using Base::disp;
    };

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)