diff --git a/images/HyTeG_GeometryMap.png b/images/HyTeG_GeometryMap.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad320f5302fab7a9b215372d40da277595ed1a0a
Binary files /dev/null and b/images/HyTeG_GeometryMap.png differ
diff --git a/images/OLAS_Solver_Hierarchy.png b/images/OLAS_Solver_Hierarchy.png
new file mode 100644
index 0000000000000000000000000000000000000000..f81f397efc8ecda2089d6f10e6a88bc19a51af96
Binary files /dev/null and b/images/OLAS_Solver_Hierarchy.png differ
diff --git a/notebooks/09_Inheritance.ipynb b/notebooks/09_Inheritance.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..1e185f36765563824c87067fdceb09742515f0d1
--- /dev/null
+++ b/notebooks/09_Inheritance.ipynb
@@ -0,0 +1,717 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "243fd0f3",
+   "metadata": {},
+   "source": [
+    "# Inheritance"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e4c244b8",
+   "metadata": {},
+   "source": [
+    "### Intro\n",
+    "\n",
+    "Following <a href=\"https://www.hanser-kundencenter.de/fachbuch/artikel/9783446458468\">[Go19]</a> the essential principles of object-oriented programming in C++ are:\n",
+    "\n",
+    " 1. **Abstraction** Classes define the methods and attributes of objects. They can also specify invariants of attributes, like e.g. that numerator and denominator of a rational number should be coprime.\n",
+    " 1. **Encapsulation** denotes the hiding of implementation details and that direct access to attributes can be prohibited, e.g. to ensure preservation of invariants.\n",
+    " 1. **Inheritance** New classes can be derived from existing ones. They retain attributes and members of their base class(es) and can extend those by adding additional ones.\n",
+    " 1. **Polymorphism** The ability of an identifier to represent different entities depending on context and/or parameters. We have seen this in the form of *static polymorphism* with overloading or templates (in the STL).\n",
+    " 1. **Late Binding** The selection of which function to invoke at run-time instead of compile-time."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e3b94e7f",
+   "metadata": {},
+   "source": [
+    "In this notebook we will introduce the basic concepts of inheritance in C++. "
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3bbe27c9",
+   "metadata": {},
+   "source": [
+    "Example of a class hierarchy from the *Object-oriented Linear Algebra Subsystem (OLAS)*\n",
+    "<img src=\"../images/OLAS_Solver_Hierarchy.png\" width=\"500\"/>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7dec0ace",
+   "metadata": {},
+   "source": [
+    "While one can be tempted to design elaborate and deep class hierarchies, this is not necessarily considered optimal design today. Especially in Scientific Programming class hierarchies tend to be relatively flat.\n",
+    "\n",
+    "The example below shows the children of the `GeometryMap` base class in <a href=\"https://i10git.cs.fau.de/hyteg/hyteg\">HyTeG</a>:\n",
+    "<img src=\"../images/HyTeG_GeometryMap.png\" width=\"250\"/>\n",
+    "\n",
+    "Below we will learn, why it can be sensible to have a single base class for multiple different, but related, classes."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "82b7f24f",
+   "metadata": {},
+   "source": [
+    "Let us start with a (slightly modified) example from <a href=\"https://www.hanser-kundencenter.de/fachbuch/artikel/9783446458468\">[Go19]</a>. It is loosely motivated by designing entry types for a database of diffent types of persons."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "2d5d1305",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#include <iostream>\n",
+    "#include <string>"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1f3df848",
+   "metadata": {},
+   "source": [
+    "We start with a simple base type for a generic human being. This will provide a classical setter and getter method for its private `name` attribute."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "id": "686fb768",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class person {\n",
+    "\n",
+    "public:\n",
+    "  person() = default;\n",
+    "  person( const std::string& name ) : name(name) {};\n",
+    "\n",
+    "  void set_name( const std::string& n ) { name = n; }\n",
+    "  std::string get_name() const { return name; }\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[person]   My name is \" << name << std::endl;\n",
+    "  }\n",
+    "\n",
+    "private:\n",
+    "  std::string name;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "cdc267d6",
+   "metadata": {},
+   "source": [
+    "Now let's introduce a special kind of persons: students. A student of course also has a name, but additionally a program in which they study.\n",
+    "\n",
+    "In this sense a student `class` is a specialisation of the `person` class.\n",
+    "\n",
+    "We can express this by inheritance and also reuse methods and attributes from the base class. "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "id": "9c807fff",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class student : public person {\n",
+    "\n",
+    "public:\n",
+    "  student( const std::string& name, const std::string program ) :\n",
+    "    person(name), program(program) {}\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[student]  My name is \" << get_name()\n",
+    "              << \", I study \" << program << std::endl;\n",
+    "  }\n",
+    "\n",
+    "private:\n",
+    "  std::string program;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "264f432a",
+   "metadata": {},
+   "source": [
+    "- Line 1 expresses that `student` is derived from `person`; in our example we perform *public* inheritance; there are also *protected* and *private* inheritance, but we will not consider those.\n",
+    "- Line 5 is also interesting; `student` is a `person` and we can select the constructor for its `person` parts.\n",
+    "- Line 8: Why do we use the getter method `get_name()` here?"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "6c7ce817",
+   "metadata": {},
+   "source": [
+    "Answer to the question is that `student` has no access to `person::name` because the latter is marked `private`. However, it inherits `name`, that's also why the constructor delegation worked.\n",
+    "\n",
+    "**Note:** A child inherits **all** methods and attributes from its parent, but necessarily access to these."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "5701c347",
+   "metadata": {},
+   "source": [
+    "Now let's play a little bit with our two classes:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "bd768c68",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "int main() {\n",
+    "\n",
+    "  person jane( \"Jane Doe\" );\n",
+    "  jane.all_info();\n",
+    "\n",
+    "  student joe( \"Joe Smith\", \"Geophysics\" );\n",
+    "  joe.all_info();\n",
+    "\n",
+    "  person pv(joe);\n",
+    "  person& pr(joe);   // or pr = joe\n",
+    "  person* pp(&joe);  // or pp = &joe\n",
+    "\n",
+    "  pv.all_info();\n",
+    "  pr.all_info();\n",
+    "  pp->all_info();\n",
+    "}"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "780348e2",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[person]   My name is Jane Doe\n",
+      "[student]  My name is Joe Smith, I study Geophysics\n",
+      "[person]   My name is Joe Smith\n",
+      "[person]   My name is Joe Smith\n",
+      "[person]   My name is Joe Smith\n"
+     ]
+    }
+   ],
+   "source": [
+    "main();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fb1056d7",
+   "metadata": {},
+   "source": [
+    "- The first two lines are what we could expect.\n",
+    "- The last three lines are maybe a little surprising. Although `joe` is an object of class `student` all calls to `all_info()` used `person::all_info()`.\n",
+    "\n",
+    "A `student` is also a `person`. However, in line 9, when we instantiate `pv` only the `person` part of joe will be copied in the initialisation, as `pv` is of type `person`.\n",
+    "\n",
+    "Similarly because we use a `person reference` and a `person pointer` we can associated them with joe, but invoking `all_info()` will use the method from the `person` class."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1ef26e9c",
+   "metadata": {},
+   "source": [
+    "### Some details on Inheritance"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "f4cbc44d",
+   "metadata": {},
+   "source": [
+    "#### Protected\n",
+    "We had seen that we do not inherit access to private data members of a base class.\n",
+    "\n",
+    "Making the base class members public would, of course, provide access. But that is not an attrative solution. The way out is to make the members `protected`. This still disallows external access, like with `private`, but opens it up for children."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "id": "fd4597ea",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class person {\n",
+    "\n",
+    "public:\n",
+    "  person() = default;\n",
+    "  person( const std::string& name ) : name(name) {};\n",
+    "\n",
+    "  void set_name( const std::string& n ) { name = n; }\n",
+    "  std::string get_name() const { return name; }\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[person]   My name is \" << name << std::endl;\n",
+    "  }\n",
+    "\n",
+    "protected:\n",
+    "  std::string name;\n",
+    "};\n",
+    "\n",
+    "class student : public person {\n",
+    "\n",
+    "public:\n",
+    "  student( const std::string& name, const std::string program ) :\n",
+    "    person(name), program(program) {}\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[student]  My name is \" << name\n",
+    "              << \", I study \" << program << std::endl;\n",
+    "  }\n",
+    "\n",
+    "private:\n",
+    "  std::string program;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "459b408f",
+   "metadata": {},
+   "source": [
+    "Having changed `name` from `private` to `protected` in line 14, allows us to directly use it in line 25."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "5c2921f9",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[person]   My name is Jane Doe\n",
+      "[student]  My name is Joe Smith, I study Geophysics\n",
+      "[person]   My name is Joe Smith\n",
+      "[person]   My name is Joe Smith\n",
+      "[person]   My name is Joe Smith\n"
+     ]
+    }
+   ],
+   "source": [
+    "main();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "0339f35f",
+   "metadata": {},
+   "source": [
+    "#### Shadowing\n",
+    "\n",
+    "What happens, when a member with the same name exists in a base class and one of its children?\n",
+    "\n",
+    "In that case the base class member is *shadowed*. However, it is still inherited and accessible with special syntax for correct resolution, see line 8 below."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "4d0cddfe",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "struct A {\n",
+    "  A( int iVal ) : value(iVal) {};\n",
+    "  int value;\n",
+    "};\n",
+    "\n",
+    "struct B : public A {\n",
+    "  B( int iVal, double dVal ) : A(iVal), value(dVal) {\n",
+    "    std::cout << \"A::value = \" << A::value << \"\\n\"\n",
+    "              << \"B::value = \" << value << std::endl;\n",
+    "  };\n",
+    "  double value;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "9e8483cd",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "A::value = 2\n",
+      "B::value = 3.5\n"
+     ]
+    }
+   ],
+   "source": [
+    "int main() {\n",
+    "  B obj( 2, 3.5 );\n",
+    "}\n",
+    "\n",
+    "main();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "4510c881",
+   "metadata": {},
+   "source": [
+    "Note that this (unfortunately) also applies to overloaded methods:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "a1919205",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class Parent {\n",
+    "public:\n",
+    "  void func() { std::cout << \"Parent::func() was called!\" << std::endl; }\n",
+    "};\n",
+    "\n",
+    "class Child : public Parent {\n",
+    "public:\n",
+    "  void func( int arg ) {\n",
+    "    std::cout << \"Child::func() was called with argument '\"\n",
+    "              << arg << \"'\" << std::endl;\n",
+    "  }\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "742d12ee",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Child::func() was called with argument '7'\n",
+      "Parent::func() was called!\n"
+     ]
+    }
+   ],
+   "source": [
+    "Child son;\n",
+    "\n",
+    "son.func( 7 );\n",
+    "\n",
+    "// son.func(); // fails, as it is shadowed, although it has a differens signature!\n",
+    "\n",
+    "son.Parent::func(); // but it is still available"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "537d3f13",
+   "metadata": {},
+   "source": [
+    "We can make that syntactically nicer with the help of a `using` directive."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "7976790d",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class AnotherChild : public Parent {\n",
+    "\n",
+    "public:\n",
+    "  void func( int arg ) {\n",
+    "    std::cout << \"Child::func() was called with argument '\"\n",
+    "              << arg << \"'\" << std::endl;\n",
+    "  }\n",
+    "\n",
+    "// private: // note that also the using directive has a visibility!\n",
+    "  using Parent::func;   // \"import\"\n",
+    "    \n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "id": "869bae76",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Child::func() was called with argument '2'\n",
+      "Parent::func() was called!\n"
+     ]
+    }
+   ],
+   "source": [
+    "AnotherChild daughter;\n",
+    "\n",
+    "daughter.func( 2 );\n",
+    "daughter.func();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "796c4abb",
+   "metadata": {},
+   "source": [
+    "#### Constructors\n",
+    "Constructors are special as the are **not implicitely inherited**, as we can see from the following example:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "d1ea8b46",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "\u001b[1minput_line_20:3:13: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mno matching constructor for initialization of '__cling_N514::researcher'\u001b[0m\n",
+      " researcher smart( \"Smartie Clever\");\n",
+      "\u001b[0;1;32m            ^      ~~~~~~~~~~~~~~~~\n",
+      "\u001b[0m\u001b[1minput_line_20:1:7: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate constructor (the implicit copy constructor) not viable: no known\n",
+      "      conversion from 'const char [15]' to 'const __cling_N514::researcher' for\n",
+      "      1st argument\u001b[0m\n",
+      "class researcher : public person {};\n",
+      "\u001b[0;1;32m      ^\n",
+      "\u001b[0m\u001b[1minput_line_20:1:7: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate constructor (the implicit move constructor) not viable: no known\n",
+      "      conversion from 'const char [15]' to '__cling_N514::researcher' for 1st\n",
+      "      argument\u001b[0m\n",
+      "class researcher : public person {};\n",
+      "\u001b[0;1;32m      ^\n",
+      "\u001b[0m\u001b[1minput_line_20:1:7: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate constructor (the implicit default constructor) not viable: requires 0\n",
+      "      arguments, but 1 was provided\u001b[0m\n"
+     ]
+    },
+    {
+     "ename": "Interpreter Error",
+     "evalue": "",
+     "output_type": "error",
+     "traceback": [
+      "Interpreter Error: "
+     ]
+    }
+   ],
+   "source": [
+    "class researcher : public person {};\n",
+    "researcher smart( \"Smartie Clever\");"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "1fbaa676",
+   "metadata": {},
+   "source": [
+    "We can solve this be explicitely requesting inheritance of the constructor again with a `using` directive. Note that this will inherit all constructors, it cannot be done selectively."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "id": "481fc3f5",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Smartie Clever\n"
+     ]
+    }
+   ],
+   "source": [
+    "class researcher : public person {\n",
+    "   using person::person;\n",
+    "};\n",
+    "researcher smart( \"Smartie Clever\");\n",
+    "std::cout << smart.get_name() << std::endl;"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "56e3203f",
+   "metadata": {},
+   "source": [
+    "When we implement a constructor in the derived class with the same signature, that one is prefered over the inherited one."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "id": "ed941226",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Hello Smartie Clever\n"
+     ]
+    }
+   ],
+   "source": [
+    "class researcher : public person {\n",
+    "   using person::person; \n",
+    "public:\n",
+    "    researcher( const std::string& n ) {\n",
+    "        name = n;\n",
+    "        std::cout << \"Hello \" << name << std::endl;\n",
+    "    }\n",
+    "};\n",
+    "researcher smart( \"Smartie Clever\");"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "fefc9ca9",
+   "metadata": {},
+   "source": [
+    "***\n",
+    "Note: \n",
+    "* When a child object is instantiated the constructors of its base classes are called first.\n",
+    "* Similarly when the child object is destroyed the destructors of its base classes are executed recursively."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "1493af7c",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class GrandParent {\n",
+    "public:\n",
+    "  GrandParent() { std::cout << \"GrandParent's c'tor invoked\" << std::endl; }\n",
+    "  ~GrandParent() { std::cout << \"GrandParent's d'tor invoked\" << std::endl; }\n",
+    "};\n",
+    "\n",
+    "class Parent : public GrandParent {\n",
+    "public:\n",
+    "  Parent() { std::cout << \"Parent's c'tor invoked\" << std::endl; }\n",
+    "  ~Parent() { std::cout << \"Parent's d'tor invoked\" << std::endl; }\n",
+    "};\n",
+    "\n",
+    "class Child : public Parent {\n",
+    "public:\n",
+    "  Child() { std::cout << \"Child's c'tor invoked\" << std::endl; }\n",
+    "  ~Child() { std::cout << \"Child's d'tor invoked\" << std::endl; }\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "id": "7802babb",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "GrandParent's c'tor invoked\n",
+      "Parent's c'tor invoked\n"
+     ]
+    }
+   ],
+   "source": [
+    "Parent walton;"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "id": "57215968",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "GrandParent's c'tor invoked\n",
+      "Parent's c'tor invoked\n",
+      "Child's c'tor invoked\n"
+     ]
+    }
+   ],
+   "source": [
+    "auto jim_bob = new Child;"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "id": "be7a63fe",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Child's d'tor invoked\n",
+      "Parent's d'tor invoked\n",
+      "GrandParent's d'tor invoked\n"
+     ]
+    }
+   ],
+   "source": [
+    "delete jim_bob;"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "aaaf7260",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++14",
+   "language": "C++14",
+   "name": "xcpp14"
+  },
+  "language_info": {
+   "codemirror_mode": "text/x-c++src",
+   "file_extension": ".cpp",
+   "mimetype": "text/x-c++src",
+   "name": "c++",
+   "version": "14"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/notebooks/10_Polymorphic_Classes.ipynb b/notebooks/10_Polymorphic_Classes.ipynb
new file mode 100644
index 0000000000000000000000000000000000000000..df655b198c5ed6c63d80d33f1fb87d8a5999ec1b
--- /dev/null
+++ b/notebooks/10_Polymorphic_Classes.ipynb
@@ -0,0 +1,435 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "id": "1a6233be",
+   "metadata": {},
+   "source": [
+    "# Polymorphic or Virtual Classes"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "7ec80016",
+   "metadata": {},
+   "source": [
+    "We return to our example from [Go19] and extend it a little."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "id": "7942848b",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#include <iostream>\n",
+    "\n",
+    "class person {\n",
+    "\n",
+    "public:\n",
+    "  person( const std::string& name ) : name(name) {};\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[person]   My name is \" << name << std::endl;\n",
+    "  }\n",
+    "\n",
+    "protected:\n",
+    "  std::string name;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "id": "f40024e2",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class student : public person {\n",
+    "\n",
+    "public:\n",
+    "  student( const std::string& name, const std::string program ) :\n",
+    "    person(name), program(program) {}\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[student]  My name is \" << name\n",
+    "              << \", I study \" << program << std::endl;\n",
+    "  }\n",
+    "\n",
+    "private:\n",
+    "  std::string program;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "id": "459a1ce0",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class researcher : public person {\n",
+    "\n",
+    "public:\n",
+    "  researcher( const std::string& name, const std::string& field ) :\n",
+    "    person(name), field(field) {}\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[researcher]  My name is \" << name\n",
+    "              << \", I work on problems in \" << field << std::endl;\n",
+    "  }\n",
+    "\n",
+    "private:\n",
+    "  std::string field;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "c5c9fb7a",
+   "metadata": {},
+   "source": [
+    "As `student`s and `researcher`s are `person`s we can e.g. generated a vector of person pointers, where each pointer targets a different university member."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "id": "5ff4684f",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#include <vector>\n",
+    "\n",
+    "student joe( \"Joe\", \"Geophysics\" );\n",
+    "student jane( \"Jane\", \"Geology\" );\n",
+    "\n",
+    "researcher erika( \"Erika\", \"Seismology\" );\n",
+    "person franz( \"Franz\" );\n",
+    "\n",
+    "std::vector<person*> uniMembers;\n",
+    "\n",
+    "uniMembers.push_back( &joe );\n",
+    "uniMembers.push_back( &jane );\n",
+    "uniMembers.push_back( &erika );\n",
+    "uniMembers.push_back( &franz );"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "56cad921",
+   "metadata": {},
+   "source": [
+    "* Because of inheritance, we can now have all pointers to our different people in the same vector, although the targeted objects are of different type.\n",
+    "* Problem is, when we work with the vectors and ask for info we only get the minimal stuff from the base class"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "id": "aebeaf35",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[person]   My name is Joe\n",
+      "[person]   My name is Jane\n",
+      "[person]   My name is Erika\n",
+      "[person]   My name is Franz\n"
+     ]
+    }
+   ],
+   "source": [
+    "for( auto memb: uniMembers ) memb->all_info();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "3f7ae736",
+   "metadata": {},
+   "source": [
+    "Instead of the full records, such as"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "id": "445c4d28",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[student]  My name is Jane, I study Geology\n",
+      "[researcher]  My name is Erika, I work on problems in Seismology\n"
+     ]
+    }
+   ],
+   "source": [
+    "jane.all_info();\n",
+    "erika.all_info();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "977efc72",
+   "metadata": {},
+   "source": [
+    "The solution to this is to make our classes **polymorphic**.\n",
+    "\n",
+    "*Definition:*   \n",
+    "A class that contains at least one **virtual function** is called **polymorphic** or **virtual**."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "id": "4b596bd2",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "#include <iostream>\n",
+    "\n",
+    "class person {\n",
+    "\n",
+    "public:\n",
+    "  person( const std::string& name ) : name(name) {};\n",
+    "\n",
+    "  virtual void all_info() const {\n",
+    "    std::cout << \"[person]      My name is \" << name << std::endl;\n",
+    "  }\n",
+    "\n",
+    "protected:\n",
+    "  std::string name;\n",
+    "};\n",
+    "\n",
+    "class student : public person {\n",
+    "\n",
+    "public:\n",
+    "  student( const std::string& name, const std::string program ) :\n",
+    "    person(name), program(program) {}\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[student]     My name is \" << name\n",
+    "              << \", I study \" << program << std::endl;\n",
+    "  }\n",
+    "\n",
+    "private:\n",
+    "  std::string program;\n",
+    "};\n",
+    "\n",
+    "class researcher : public person {\n",
+    "\n",
+    "public:\n",
+    "  researcher( const std::string& name, const std::string& field ) :\n",
+    "    person(name), field(field) {}\n",
+    "\n",
+    "  void all_info() const {\n",
+    "    std::cout << \"[researcher]  My name is \" << name\n",
+    "              << \", I work on problems in \" << field << std::endl;\n",
+    "  }\n",
+    "\n",
+    "private:\n",
+    "  std::string field;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "id": "12bebbf9",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[student]     My name is Joe, I study Geophysics\n",
+      "[student]     My name is Jane, I study Geology\n",
+      "[researcher]  My name is Erika, I work on problems in Seismology\n",
+      "[person]      My name is Franz\n"
+     ]
+    }
+   ],
+   "source": [
+    "#include <vector>\n",
+    "\n",
+    "student joe( \"Joe\", \"Geophysics\" );\n",
+    "student jane( \"Jane\", \"Geology\" );\n",
+    "\n",
+    "researcher erika( \"Erika\", \"Seismology\" );\n",
+    "person franz( \"Franz\" );\n",
+    "\n",
+    "std::vector<person*> uniMembers;\n",
+    "\n",
+    "uniMembers.push_back( &joe );\n",
+    "uniMembers.push_back( &jane );\n",
+    "uniMembers.push_back( &erika );\n",
+    "uniMembers.push_back( &franz );\n",
+    "\n",
+    "for( auto memb: uniMembers ) memb->all_info();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ef04a619",
+   "metadata": {},
+   "source": [
+    "**Explanation**  \n",
+    "So what is the difference here? Whenever we work with a **pointer** `pVar` or a **reference** `rVar` to a class and invoke a function `myFunc()` via that on the target the compiler will check the following:\n",
+    "\n",
+    "1. What is the **static type** of `pVal` and or `pVar`, i.e. how were they declared?\n",
+    "1. Does that class have a method `myFunc()`?\n",
+    "1. Is `myFunc()` accessible, i.e. public, or not, i.e. private?\n",
+    "1. Is it a **virtual function**?\n",
+    "   * No: Then invoke it.\n",
+    "   * Yes: Check what the **dynamic type** is of `pVal` and or `pVar`, i.e. the type of the object they target.\n",
+    "   Then invoke `myFunc()` for that type."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ae46b4e3",
+   "metadata": {},
+   "source": [
+    "**Remark #1:**  \n",
+    "This only works for pointers and references, but not for variables, even if they are initialised or copy constructed from a child object."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "ccb162c8",
+   "metadata": {
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[person]      My name is Joe\n"
+     ]
+    }
+   ],
+   "source": [
+    "person alias{joe};\n",
+    "alias.all_info();"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "2d6da352",
+   "metadata": {},
+   "source": [
+    "Only the parts of `joe` that belong to its `person` base class are used for the initialisation. This is sometimes refered to as **slicing**."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "ad22ac97",
+   "metadata": {},
+   "source": [
+    "**Remark #2:**  \n",
+    "The decision which version of `all_info()` must be invoked **cannot** be made by the compiler, as it may not have the necessary information on the type of the target of a pointer or reference. It can only be made at **runtime**."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "bcb61161",
+   "metadata": {},
+   "source": [
+    "#### Terminology\n",
+    "Since the decision which virtual method is invoked on a pointer or reference to a polymorphic object is performed at runtime, one calls this **late** or **dynamic binding**.\n",
+    "\n",
+    "It constitutes a form of **dynamic polymorphism**, as opposed to the static polymorphism of overloading or templates, which get's resolved at compile-time."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "370a4417",
+   "metadata": {},
+   "source": [
+    "#### Costs\n",
+    "In order to be able to correctly dispatch the virtual function call at runtime, the compiler generates a **virtual function table** (also **virtual method table**, **vtable**, **dispatch table**). The necessary table lookup constitutes an indirection and increases the costs for the function invokation.\n",
+    "\n",
+    "If your function is short (i.e. does not perform a lot of work) then this extra overhead can be critically significant. If you function is long is will be negligible."
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "e27f36b9",
+   "metadata": {},
+   "source": [
+    "### Overriding"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "id": "960b3f74",
+   "metadata": {},
+   "source": [
+    "In our example all child classes (`student` and `researcher`) have implemented their own version of `all_info()` and, thus, **overridden** the one from the base class. This is, however, not required. If the base class method is not overridden in a child, the base class method will simply be used."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "99352379",
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "class staff : public person{\n",
+    "    using person::person;\n",
+    "};"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "id": "454ccaaf",
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "[person]      My name is Linda\n"
+     ]
+    }
+   ],
+   "source": [
+    "person* secretary = new staff( \"Linda\" );\n",
+    "secretary->all_info();"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "id": "9f63ea43",
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "C++14",
+   "language": "C++14",
+   "name": "xcpp14"
+  },
+  "language_info": {
+   "codemirror_mode": "text/x-c++src",
+   "file_extension": ".cpp",
+   "mimetype": "text/x-c++src",
+   "name": "c++",
+   "version": "14"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}