// From http://en.cppreference.com/w/cpp/language/virtual
//
// Build with:        g++ -Wall -o inh inh.cc
// Disassemble with:  objdump -d inh  OR  gobjdump -d inh  (On MacOS)

#include <iostream>

struct Base {
     int a = 0, b = 0 , c = 0;          
     // The above causes a 'C++11' warning. To avoid the warning, change to explicit initialization in the constructor:
     // int a, b, c; 
     // Base() { a = 0; b = 0; c = 0; } //  OR Base() : a(0), b(0), c(0) { }
          
     virtual void foo() {         // <--- note "virtual"! This adds a VPTRs to each Base and Derived object instance, 
                                  //        and a VTABLE per each class. Find references to these in disassembly.
          std::cout << "base\n";
     }
};

// every object of type Derived includes Base as a subobject
struct Derived : Base {
     int b = 1;    // this will shadow the Base's b, depending on how it's accessed (see below)

     // Same deal about the warning:
     // int b;
     // Derived() { b = 1; } // OR  Derived() : b(1) { } 
     

     void foo() {  // OR: void f() override { // 'override' is optional
          std::cout << "derived\n";
     }
};

int main()
{
     Base b;
     Derived d;
     
     Base*    bp = &b; // 
     Derived* dp = &d; // Try this with Base* first, notice where the output differs---and doesn't!
     bp->foo();        //   prints "base"
     dp->foo();        //   prints "derived"

     // Calling a method of an object through the base class pointer.  
     bp = (Base *) &d;
     bp->foo();        // <----- this is the heart of C++ inheritance-based OO!  
     
     std::cout << "member b via ptr: " << bp->b << " " << dp->b << std::endl;

     return 0;
}

