diff --git a/2-ObjectProgramming/6-inheritance.ipynb b/2-ObjectProgramming/6-inheritance.ipynb index b9006307b3a573a96898468821720e98b91bdcbc..e7f160a1cc004400af340e4a9ced5e303b8c26fd 100644 --- a/2-ObjectProgramming/6-inheritance.ipynb +++ b/2-ObjectProgramming/6-inheritance.ipynb @@ -1320,6 +1320,108 @@ "}" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Beware:** You **must** provide a definition for all non pure-virtual methods in your class. Not doing so leads to a somewhat cryptic error at link-time.\n", + "\n", + "You are not required to provide a definition for a pure virtual method, and you won't most of the time... But you might provide one if you want to do so, for instance to provide an optional default instantiation for the method in derived classes:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "struct VirtualBase\n", + "{\n", + " virtual void Method() = 0;\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#include <iostream>\n", + "\n", + "void VirtualBase::Method()\n", + "{\n", + " std::cout << \"Default implementation provided in abstract class.\" << std::endl;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "struct Concrete1 : public VirtualBase\n", + "{\n", + " virtual void Method() override;\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "struct Concrete2 : public VirtualBase\n", + "{\n", + " virtual void Method() override;\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "void Concrete1::Method()\n", + "{\n", + " VirtualBase::Method(); // call to the method defined in the base class\n", + " std::cout << \"This enables providing a base behaviour that might be completed if needed \"\n", + " \"in derived classes, such as here by these lines you are reading!\" << std::endl;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "void Concrete2::Method()\n", + "{\n", + " std::cout << \"Overriden implementation.\" << std::endl;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "{\n", + " std::cout << \"====== Concrete 1: uses up the definition provided in base class =====\" << std::endl;\n", + " Concrete1 concrete1;\n", + " concrete1.Method();\n", + "\n", + " std::cout << \"\\n====== Concrete 2: doesn't use the definition provided in base class =====\" << std::endl;\n", + " Concrete2 concrete2;\n", + " concrete2.Method();\n", + "}" + ] + }, { "cell_type": "markdown", "metadata": {},