CHAPTER 14

image

Inheritance

Inheritance allows a class to acquire the members of another class. In the example below, Square inherits from Rectangle. This is specified after the class name by using a colon followed by the public keyword, and the name of the class to inherit from. Rectangle then becomes a base class of Square, which in turn becomes a derived class of Rectangle. In addition to its own members, Square gains all accessible members in Rectangle, except for its constructors and destructor.

class Rectangle
{
  public:
    int x, y;
    int getArea() { return x * y; }
};

class Square : public Rectangle {};

Upcasting

An object can be upcast to its base class, because it contains everything that the base class contains. An upcast is performed by assigning the object to either a reference or a pointer of its base class type. In the example below, a Square object is upcast to Rectangle. When using Rectangle’s interface the Square object will be viewed as a Rectangle, so only Rectangle’s members can be accessed.

Square s;
Rectangle& r = s;  // reference upcast
Rectangle* p = &s; // pointer upcast

A derived class can be used anywhere a base class is expected. For example, a Square object can be passed as an argument to a function that expects a Rectangle object. The derived object will then implicitly be upcast to its base type.

void setXY(Rectangle& r) { r.x = 2; r.y = 3; }

int main()
{
  Square s;
  setXY(s);
}

Downcasting

A Rectangle reference that points to a Square object can be downcast back to a Square object. This downcast has to be made explicit since downcasting an actual Rectangle to a Square is not allowed.

Square& a = (Square&) r;  // reference downcast
Square& b = (Square&) *p; // pointer downcast

Constructor Inheritance

To make sure the fields in the base class are properly initialized, the parameterless constructor of the base class is automatically called when an object of the derived class is created.

class B1
{
 public:
  int x;
  B1() : x(5) {}
};

class D1 : public B1 {};

int main()
{
 // Calls parameterless constructors of D1 and B1
 D1 d;
 cout << d.x; // "5"
}

This call to the base constructor can be made explicitly from the derived constructor, by placing it in the constructor’s initialization list. This allows arguments to be passed along to the base constructor.

class B2
{
 public:
  int x;
  B2(int a) : x(a) {}
};

class D2 : public B2
{
 public:
  D2(int i) : B2(i) {} // call base constructor
};

An alternative solution in this case is to inherit the constructor. As of C++11, this can be done through a using statement.

class D2 : public B2
{
 public:
  using B2::B2; // inherit all constructors
  int y{0};
};

Note that the base class constructor cannot initialize fields defined in the derived class. Therefore, any fields declared in the derived class should initialize themselves. This is done here using the uniform notation.

Multiple Inheritance

C++ allows a derived class to inherit from more than one base class. This is called multiple inheritance. The base classes are specified in a comma-separated list.

class Person {}
class Employee {}

class Teacher: public Person, public Employee {}

Multiple inheritance is not commonly used since most real-world relationships can be better described by single inheritance. It also tends to significantly increase the complexity of the code.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.144.248