mixed.cc

#include <iostream>  // cout, endl
#include <cstdlib>   // EXIT_SUCCESS

using std::cout;
using std::endl;

class A {
 public:
  void M1() { cout << "a1, "; }
  virtual void M2() { cout << "a2"; }
};

class B : public A {
 public:
  void M1() { cout << "b1, "; }
  void M2() { cout << "b2"; }
};

int main(int argc, char** argv) {
  A a;
  B b;
  A* a_ptr_a = &a;
  A* a_ptr_b = &b;
  // B* ba_ptr = &a;  // compiler error
  B* b_ptr_b = &b;

  a_ptr_a->M1();
  a_ptr_a->M2();
  cout << endl;
  a_ptr_b->M1();
  a_ptr_b->M2();
  cout << endl;
  b_ptr_b->M1();
  b_ptr_b->M2();
  cout << endl;

  return EXIT_SUCCESS;
}

badctor.cc

// Base has no default constructor
class Base {
 public:
  Base(int y) : y(y) { }
  int y;
};

// Compiler error when you try to instantiate a D1, as D1’s
// synthesized default constructor needs to invoke Base's default
// constructor.
class Der1 : public Base {
 public:
  int z;
};

// Works.
class Der2 : public Base {
 public:
  Der2(int y, int z) : Base(y), z(z) { }
  int z;
};

int main(int argc, char **argv) {
  Base b(1);   // OK
  Der2 d2(1, 2);  // OK
  // Der1 d1;     // compiler error
  return 0;
}

goodctor.cc

// Base has a default constructor.
class Base {
 public:
  int y;
};

// Works.
class Der1 : public Base {
 public:
  int z;
};

// Works.
class Der2 : public Base {
 public:
  Der2(int z) : z(z) { }
  int z;
};

int main(int argc, char **argv) {
  Base b;      // OK
  Der2 d2(1);  // OK
  Der1 d1;     // OK
  return 0;
}

baddtor.cc

#include <iostream>

class Base {
 public:
  Base()  { std::cout << "Base()"  << std::endl; x = new int; }
  ~Base() { std::cout << "~Base()" << std::endl; delete x; }
  int* x;
};

class Der1 : public Base {
 public:
  Der1()  { std::cout << "Der1()"  << std::endl; y = new int; }
  ~Der1() { std::cout << "~Der1()" << std::endl; delete y; }
  int* y;
};

int main(int argc, char** argv) {
  Base* b0ptr = new Base;
  Base* b1ptr = new Der1;

  delete b0ptr;  // OK
  delete b1ptr;  // leaks Der1::y

  return 0;
}

slicing.cc

class Base {
 public:
  Base(int x) : x(x) { }
  int x;
};

class Der1 : public Base {
 public:
  Der1(int y) : Base(16), y(y) { }
  int y;
};

int main(int argc, char** argv) {
  Base b(1);
  Der1 d(2);
  b = d;  // what happens to y?
  // d = b;  // compiler error
}

static_cast

class A {
 public:
  int x;
};

class B {
 public:
  float x;
};

class C : public B {
 public:
  char x;
};

int main(int argc, char** argv) {
  B b; C c;

  // compiler error
  A* aptr = static_cast<A*>(&b);
  // OK
  B* bptr = static_cast<B*>(&c);
  // compiles, but dangerous
  C* cptr = static_cast<C*>(&b);

  return 0;
}

dynamiccast.cc

#include <cassert>

class Base {
 public:
  // virtual function included to make hierarchy polymorphic
  virtual void foo() { }
  float x;
};

class Der1 : public Base {
 public:
  char x;
};

int main(int argc, char** argv) {
  Base b; Der1 d;

  // OK (run-time check passes)
  Base* bptr = dynamic_cast<Base*>(&d);
  assert(bptr != nullptr);

  // OK (run-time check passes)
  Der1* dptr = dynamic_cast<Der1*>(bptr);
  assert(dptr != nullptr);

  // Run-time check fails, so the cast returns nullptr
  bptr = &b;
  dptr = dynamic_cast<Der1*>(bptr);
  assert(dptr != nullptr);

  return 0;
}

constcast.cc

void foo(int* x) {
  (*x)++;
}

void bar(const int* x) {
  // foo(x);                    // compiler error
  foo(const_cast<int*>(x));  // succeeds
}

int main(int argc, char** argv) {
  int x = 7;
  bar(&x);
  return 0;
}