C++ recap: Inheritance

Example #1:

#include <iostream>

class Base {
public:
  int value;

  Base(int v = 0)
    : value(v)
  {}
};

class Derived: public Base {
public:
  double dValue;

  Derived(int v, double d = 2.22)
    : Base(v), dValue(d)
  {}

  /* We need to call the Base constructor to 
     initialize Base member values; why? 
     To make sure that subsequent constructors 
     of derived classes do not override a base
     class const variable.
     Const values and references are always 
     initialized in the initialization list 
     of the constructor */
};


int main() {
  using namespace std;

  Derived d(2,3);
  cout << d.value << endl;
  cout << d.dValue << endl;
  
  return 0;
}

Example #2:

#include <iostream>
using namespace std;

/*
  Member variables can be accessed according to the 
  access specifiers:
  - private: by member functions only
  - protected: by member functions and derived classes
  - public: by anybody

  A derived class accesses inherited members based 
  on the access specifiers of its immediate parent
*/

class Base {
private:
  int priv;
protected:
  int prot;
public:
  int publ;

  Base(int a = 0, int b = 0, int c = 0)
    : priv(a), prot(b), publ(c)      
  {}
};

/* Public inheritance:
   all members keep their original access specifications.
*/

class publicDerived : public Base {
public:
  publicDerived() {
    // priv = 9; // no
    prot = 9; 
    publ = 9; 
  }
};


/* Private inheritance:
   everything bumps up to private */
class privateDerived : private Base {
public:
  privateDerived() {
    // priv = 9; // no
    prot = 9;
    publ = 9;
  }
};


/* Protected inheritance:
   everything bumps up to protected */
class protectedDerived : protected Base {
public:
  protectedDerived() {
    // priv = 9; // no
    prot = 9;
    publ = 9;
  }
};

int main() {

  publicDerived d1;
  // cout << d1.priv; // no
  // cout << d1.prot; // no
  cout << d1.publ;

  privateDerived d2;
  // cout << d2.priv; // no
  // cout << d2.prot; // no
  // cout << d2.publ; // no

  protectedDerived d3;
  // cout << d3.priv; // no
  // cout << d3.prot; // no
  // cout << d3.publ; // no

  return 0;
}

Common patterns:

1) I don’t want anyone to be able to create a Base class object directly, but only Derived1 and Derived2 objects.
=> make the Base constructor protected

|