Hierarchical Classifications. Characteristics Common: Inheritance
Hierarchical Classifications. Characteristics Common: Inheritance
A class that is inherited is referred to as a base class. The class that does
the inheriting is called the derived class.
Further, a derived class can be used as a base class for another derived
class. In this way, multiple inheritance is achieved.
Base-Class Access Control
When a derived class inherits the members of the base class, the base class
members become the members of the derived class.
Class inheritance uses this general form:
class derived-class-name : access base-class-name
{
// body of class
};
The access status of the base-class members inside the derived class is determined
by access.The base-class access specifier must be either public, private, or
protected.
If no access specifier is present, the access specifier is private by default if the
derived class is a class. If the derived class is a struct, then public is the default in
the absence of an explicit access specifier.
public inheritance:
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. In all cases, the base's private elements remain private
to the base and are not accessible by members of the derived class
# include <iostream>
using namespace std;
class A { int main()
int i, j; {
public: B ob(3);
void set (int a, int b) { i=a; j=b; } ob.set(1, 2); // access member of base
void show() ob.show(); // access member of base
{ cout << i << " " << j << "\n"; } ob.showk(); // uses member of derived
}; class
class B : public A { return 0;
int k; }
public:
B(int x) { k=x; }
void showk()
{ cout << k << "\n"; }
};
private inheritance:
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.
For example, the following program will not even compile because
both set( ) and show( ) are now private elements of derived:
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. By using protected access specifier, class members can be
created that are private to their class but that can still be inherited and accessed by
a derived class.
#include <iostream>
using namespace std;
class A {
protected:
int i, j; // private to base, but accessible by derived
public:
void set(int a, int b) { i=a; j=b; } int main() {
void show() { cout << i << " " << j << "\n"; } B ob;
}; ob.set(2, 3); // accessible in derived
class
class B : public A {
ob.show(); //accessible in derived class
int k;
ob.setk();
public:
ob.showk();
// derived may access base's i and j
return 0; }
void setk() { k=i*j; }
void showk() { cout << k << "\n"; }
};
In this example, because base is inherited by derived as public and because i and j
are declared as protected, derived function setk( ) may access them. If i and j had
been declared as private by base, then derived would not have access to them, and
the program would not compile.
When a derived class is used as a base class for another derived class, any
protected member of the initial base class that is inherited (as public) by the first
derived class may also be inherited as protected again by a second derived class.
#include <iostream>
// i and j inherited indirectly through
using namespace std;
derived1.
class A {
class B2 : public B1 {
protected:
int m;
int i, j;
public:
public:
void setm()
void set(int a, int b) { i=a; j=b; }
{ m = i - j;
void show() { cout << i << " " << j << "\n"; }
} // legal
};
// i and j inherited as protected.
void showm()
class B1 : public A {
{
int k;
cout << m << "\n";
public:
}
void setk() { k = i*j; } // legal
void showk() { cout << k << "\n"; }
};
};
int main()
If, however, base were inherited as private, then all members
{
of base would become private members of derived1, which
B1 ob1;
means that they would not be accessible by derived2.
ob1.set(2, 3);
(However,i and j would still be accessible by derived1.)
ob1.show();
ob1.setk();
ob1.showk();
B2 ob2;
ob2.set(3, 4);
ob2.show();
ob2.setk();
ob2.showk();
ob2.setm();
ob2.showm();
return 0;
}
// This program won't compile. int main()
#include <iostream> {
using namespace std; B1 ob1;
class A { ob1.set(1, 2); //error, can't use set()
protected: int i, j; ob1.show(); //error, can't use show()
public: return 0;
void set(int a, int b) { i=a; j=b; } }
void show() { cout << i << " " << j << "\n"; }
};
// Now, all elements of base are private in B1.
class B1 : private base {
int k;
public:
// this is legal because i and j are private to B1
void setk() { k = i*j; } // can be invoked
void showk() { cout << k << "\n"; } // can be invoked
Protected Base-Class Inheritance
Base class members can be inherited using protected access specifier. When
inherited, all public and protected members of the base class become protected
members of the derived class.
#include <iostream>
using namespace std;
class A {
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. int main()
class B : protected A{ {
int k; B ob;
public: // ob.setij(2, 3); // setij() is protected
// derived may access base's i and j and setij(). member of derived
void setk() ob.setk(); // Can be invoked, public
{ member of derived
setij(10, 12); ob.showall(); // Can be invoked, public
k = i*j; member of derived
} // ob.showij(); // showij() is protected
// may access showij() here member of derived
void showall() return 0;
{ cout << k << " "; }
showij(); }
};
Inheriting Multiple Base Classes
A derived class can inherit two or more base classes.
Ex:#include <iostream> // Inherit multiple base classes.
using namespace std; class derived: public base1, public base2
class base1 {
{ public:
protected: void set(int i, int j)
int x; { x=i; y=j;
public: }
void showx() { cout << x << "\n"; } };
}; int main()
class base2 { {
protected: derived ob;
int y; ob.set(10, 20); // provided by derived
public: ob.showx(); // from base1
void showy() {cout << y << "\n";} ob.showy(); // from base2
}; return 0;
}
#include<iostream> class C : public A,public B
using namespace std; {
class A public:
{ void display()
protected: {
int a; cout<<"Addition of a and b is : "<<a+b;
public: cout<<"Subtraction of a and b is : "<<a-b;
void get_a(int n) cout<<"Multiplication of a and b is : "<<a*b;
{ cout<<"Division of a and b is : "<<a\b;
a=n; }
} };
};
class B
{
int main()
protected: {
int b; C c;
public: c.get_a(10);
void get_b(int n) c.get_b(20);
{
b=n;
c.display();
} return 0;
}; }
Constructors, Destructors, and Inheritance
When Constructor and Destructor Functions Are Executed Base and derived classes can have
their constructor and destructor function. Base class constructors are executed before executing
derived class constructors. Derived class destructors will be executed first before executing
base class destructors.
#include <iostream>
using namespace std; int main()
class base { {
public: derived ob;
base() { cout << "Constructing base\n"; } return 0;
~base() { cout << "Destructing base\n"; } }
};
class derived: public base {
public:
Constructing base
derived() { cout << "Constructing derived\n"; }
Constructing derived
~derived() { cout << "Destructing derived\n"; }
Destructing derived
};
Destructing base
The program constructs and then destroys an object called ob that is of class derived.
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.
then the output of this program would have looked like this:
Constructing base2
Constructing base1
Constructing derived
Destructing derived
Destructing base1
Destructing base2
Passing Parameters to Base-Class Constructors
If a base class contains parameterized constructor, it can be called explicitly from derived
class constructor.
derived-constructor(arg-list) : base1(arg-list),
base2(arg-list),
…
baseN(arg-list)
{
// body of derived constructor
}
Here, base1 through baseN are the names of the base classes inherited by the derived class.
Colon separates the derived class' constructor definition from the base-class specifications,
and that the base-class specifications are separated from each other by commas, in case of
multiple base classes.
Ex:#include <iostream> ~derived()
using namespace std; { cout << "Destructing derived\n"; }
class base { void show()
protected: { cout << i << " " << j << "\n"; }
int i; };
public:
base(int x)
{ i=x; cout << "Constructing base\n"; }
~base() { cout << "Destructing base\n"; }
}; int main() {
class derived: public base { derived ob(3, 4);
int j; ob.show(); // displays 4 3
public: return 0;
// derived uses x; y is passed along to base. }
derived(int x, int y): base(y)
{ j=x;
cout << "Constructing derived\n";
}
Multiple base class : Parameterized constructor - explicit invocation
#include <iostream> class derived: public base1, public base2 {
using namespace std; int j;
class base1 { public:
protected: derived(int x, int y, int z): base1(y), base2(z)
int i; { j=x;
public: cout << "Constructing derived\n";
base1(int x) }
{ i=x; cout << "Constructing base1\n"; } ~derived()
~base1() { cout << "Destructing base1\n"; } { cout << "Destructing derived\n"; }
}; void show() { cout << i << " " << j << " " << k << "\
class base2 { n"; }
protected: };
int k; int main()
public: {
base2(int x) { k=x; cout << "Constructing base2\n"; } derived ob(3, 4, 5);
~base2() { cout << "Destructing base1\n"; } ob.show(); // displays 4 3 5
}; return 0; }
Granting Access
When a base class is inherited as private, all public and protected members of that class
become private members of the derived class. However, in certain circumstances, it might be
necessary to restore one or more inherited members to their original access specification.
Ex: it might be necessary to grant certain public members of the base class public status in
the derived class even though the base class is inherited as private.
In Standard C++, there are two ways to accomplish this.
1. By coding “using” statement
2. By using an “access declaration” within the derived class. (deprecated)
The access declaration is put under the appropriate access heading in the derived class.
class base {
public:
int j; // public in base
};
// Inherit base as private.
class derived: private base {
public:
// here is access declaration
base::j; // make j public again
..
};
Because base is inherited as private by derived, the public member j is made a private member of
derived. However, by including
base::j;
as the access declaration under derived public heading, j is restored to its public status.
Access declaration can be used to restore the access rights of public and protected members.
However, access declaration cannot be used to raise or lower a member's access status.
Ex: a member declared as private in a base class cannot be made public by a derived class.
Program generates warning, because access-declaration syntax is deprecated.
#include <iostream> int main()
using namespace std; {
class base { derived ob;
int i; // private to base //ob.i = 10; // because i is private in derived
public:
int j, k;
ob.j = 20; // legal because j is made public in derived
void seti(int x) { i = x; } //ob.k = 30; // because k is private in derived
int geti() { return i; } ob.a = 40; // legal because a is public in derived
}; ob.seti(10);
class derived: private base { cout << ob.geti() << " " << ob.j << " " << ob.a;
public: return 0;
/* The next three statements override base's }
inheritance as private and restore j, seti(), and geti() to public access. */
base::j; // make j public again - but not k
base::seti; // make seti() public
base::geti; // make geti() public
// base::i; // illegal, cannot elevate access
int a; // public
};
Ex: Program uses ‘using’ keyword to change the access specifier of the inherited member.
No, deprecation warnings will be generated.
#include <iostream>
int main()
using namespace std;
{
class base {
derived ob;
int i; // private to base
//ob.i = 10; // because i is private in derived
public:
ob.j = 20; // legal because j is made public in
int j, k;
derived
void seti(int x) { i = x; }
//ob.k = 30; // because k is private in derived
int geti() { return i; }
ob.a = 40; // legal because a is public in derived
};
class derived: private base { ob.seti(10);
public: cout << ob.geti() << " " << ob.j << " " << ob.a;
using base::j; // make j public again - but not k return 0; }
using base::seti; // make seti() public
using base::geti; // make geti() public
Access declarations are supported in C++ to accommodate
// base::i; // illegal, cannot elevate access those situations in which most of an inherited class is intended
int a; // public to be made private, but a few members are to retain their
}; publicor protected status.
Virtual Base Classes
An element of ambiguity can be introduced into a C++ program when multiple base classes are
inherited // This program contains an error and will not compile.
#include <iostream>
using namespace std; int main() {
class base { derived3 ob;
public: int i; ob.i = 10; // this is ambiguous, which i???
}; ob.j = 20;
class derived1 : public base { ob.k = 30;
public: int j; // i ambiguous here, too
}; ob.sum = ob.i + ob.j + ob.k;
class derived2 : public base { // also ambiguous, which i?
public: int k; cout << ob.i << " ";
}; cout << ob.j << " " << ob.k << " ";
class derived3 : public derived1, public cout << ob.sum;
derived2 { return 0; }
public: int sum;
Both derived1 and derived2 inherit base. However, derived3 inherits both derived1 and
derived2. This means that there are two copies of base present in an object of type derived3.
An expression like ob.i = 10; induces ambiguity There are two copies of base present in object ob,
one from dervied1 and the other from derived2.
There are two ways to remove ambiguity.
1. To use scope resolution operator to i and manually select one i.
2. To use virtual keyword while inheriting from base to derived1 and derived2.