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
class A{ };
class B: public A {
int a; void f(); };
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.
class A{ };
class B: public A {
int a; void f(); };
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.
class A{ };
class B: public A {
int a; void f(); };
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
class A{ };
class B: public A {
int a; void f(); };
Because a derived class inherits members from all its base classes,
ambiguities can result
class A{ };
class B: public A {
int a; void f(); };
In case of ambiguous data members a solution would be to override the base class members
class A{
public:
int a; A():a(10){};
};
class B{
public:
int a; B():a(20){};
};
class C:public A,public B
{
public:
int a; };
We can still access the override members of the base class using scope resolution operator
;
};
class Derived:public Base
{
public:
int a; Derived():a(100){};
};
int main()
{
Derived c1;
cerr << c1.a << ":"<< endl; cerr << c1.Base::a << ":"<< endl; }
A direct base class cannot appear in the base list of a derived class more than once:
;
};
class Derived:public Base
{
public:
int a; Derived():a(100){};
};
int main()
{
Derived c1;
cerr << c1.a << ":"<< endl; cerr << c1.Base::a << ":"<< endl; }
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.
class Parent{
public:
int a;
}
class Base:public Parent{
public:
void disp(){cout << a << endl;}
};
class Base1:public Parent{
public:
void disp(){cout << a << endl;}
};
class Derived:private Base,private Base1
{
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.
using namespace std;
class Parent{
public:
int a;
}
class Base:public virtual Parent{
public:
void disp(){cout << a << endl;}
};
class Base1:public virtual Parent{
public:
void disp(){cout << a << endl;}
};
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.
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;}
};
class Derived:private Base,private Base1
{
public:
};
int main()
{
Derived d;
cout << d.a <<endl; }
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
class Base{
private:
int a;
public:
void disp(){cout << a << endl;}Base():a(10){};
};
class Derived:protected Base
{
public:
void disp(int a){};};
int main()
{
Derived d;
d.disp(); }
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
class Base{
private:
int a;
public:
void disp(){cout << a << endl;}
Base():a(10){};
};
class Derived:protected Base
{
public:
using Base::disp;
void disp(int a){};
};
int main()
{
Derived d;
d.disp();}
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.
class Base{
private:
int a;
public:
void disp(){cout << a << endl;} Base():a(10){};
};
class Derived:protected Base
{
public:
using Base::disp; void disp(){cerr << "DErived" << endl;};
void disp(int a){};
};
int main()
{
Derived d;
d.disp();}
Using Declaration cannot resolve ambiguities due to same inherited members
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(){}; };
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.
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(){}; };
Pointer Derived Class and Base Class
Pointer to a Derived class can be converted to pointer of the base class
class Base{
public:
int a;
Base():a(10){};
};
class Derived:public Base
{
public:
int a; Derived():a(100){};
};
int main()
{
Derived d1;
Derived *d2=&d1; Base *b1;
b1=d2; cerr << b1->a << endl;cerr << d2->a << endl;}
A pointer to base class cannot be derived to case class.
int main()
{
Derived d1;
Derived *d2=&d1; Base *b1;
d2=b1; }
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
class Base{
private:
int a;
public:
void disp(){cout << a << endl;}
Base():a(10){};
};
class Derived:private Base
{
public:
using Base::disp;
};
int main()
{
Derived d;
d.disp();}
Access to members declared as private in the base class cannot be increased
class Base{
private:
int a;
public:
void disp(){cout << a << endl;}
Base():a(10){};
};
class Derived:public Base
{
public:
using Base::a; };
Access to a member cannot be reduced with a using declaration
class Base{
private:
int a;
public:
void disp(){cout << a << endl;}
Base():a(10){};
};
class Derived:public Base
{
private: using Base::disp;
};