Code Notes: Intro to C++, part 4

Topics covered: Public inheritance, Polymorphism

Link to source code: http://www.cs.tufts.edu/comp/15/examples/CPP/ex4.cpp

#include <iostream>

using namespace std;

/*
  Inheritance: 
  1. Creates opportunity reuse code.
  2. Makes the design modular.
  3. Implements an is-a relationship.

Idea: A derived class can inherit data and functions from base classes.

A derived class is first of all a base class
 */

/*
  Static type vs dynamic type
 */

class base {
  public:

    // Presence of at least one pure virtual function 
    // makes base an abstract class
    virtual void pure_virtual_function() = 0;
    
    void non_virtual_function() 
    { 
        cout << "calling base::non_virtual_function()" << endl; 
    }
    
    virtual void virtual_function() 
    { 
        cout << "calling base::virtual_function()" << endl; 
    }
};


/*
  Public inheritance (as indicated by public base):
  * A derived class is first of all a base class
  * Public inheritance means 
  ** Public members of base class becomes public members of derived class
  ** Protected members of base class becomes protected members of derived class
  ** Private members of base class remains inaccessible to the derived class
  * Public inheritance is the most common form of inheritance
 */
class derived /* final */ : public base { // First of all a base
  public:
    void pure_virtual_function() 
    { 
        cout << "overriding derived::pure_virtual_function" << endl; 
    }
    
    void non_virtual_function() 
    { 
        cout << "calling derived::non_virtual_function()" << endl;
    }
    
    virtual void virtual_function() /* override */ 
    { 
        cout << "calling derived::virtual_function()" << endl; 
    }
};


/*
  Rules:
  1. Use a non-virtual function when derived classes will never override it.
  2. Use a virutal function when:
  (a) the base class has a meaningful implementation, and
  (b) some derived classes might override it, some might not.
  3. Use a pure virtual function when
  (a) the base class has no meaningful implemmentation, and
  (b) all derived classes MUST override it.

  When a class has at least 1 pure virtual function, it is an abstract class,
  and cannot be instantiated.
 */


/* A derived class is considered substitutable for the base class,
   irrespective of whether it is passed
   by value, by pointer or by reference. 
*/

void foo(base bval)
{
   bval.non_virtual_function();
}

void foo2(base* bptr)
{
   bptr->virtual_function();
}

void foo3(base& bref)
{
   bref.virtual_function(); 
}


int main()
{
    base* b1 = new derived();
    // Static type of (*b1) is base --> look at its definition
    // Dynamic type of (*b1) is d --> look at the object it points to

    b1->non_virtual_function(); // non-virtual functions use static type
    b1->virtual_function(); // virtual functions use dynamic type


    derived d1;
    foo(d); // Slicing --> copy constructor of base is invoked


    derived* d2 = new derived();
    foo(d2); // Pass by pointer: can never lose info

    derived d3; 
    foo3(d3); // Pass by reference: can never lose info

    return 0;
}