{"id":5325,"date":"2017-10-05T08:41:16","date_gmt":"2017-10-05T08:41:16","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-class-hierarchies\/"},"modified":"2023-06-26T12:05:03","modified_gmt":"2023-06-26T12:05:03","slug":"c-core-guidelines-class-hierarchies","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-class-hierarchies\/","title":{"rendered":"C++ Core Guidelines: Class Hierarchies"},"content":{"rendered":"<p>Let&#8217;s talk in this post about rules for class hierarchies in general and in particular. The C++ core guidelines have about thirty rules; therefore, I have a lot to discuss.<\/p>\n<p><!--more--><\/p>\n<p>First, what is a class hierarchy? The C++ core guidelines give a clear answer. Let me rephrase it. A class hierarchy represents a set of hierarchically organized concepts. Base classes typically act as interfaces. They are two uses for interfaces. One is called implementation inheritance, and the other is interface inheritance.<\/p>\n<p>The first three lines are more general, or to say it differently: they summarize the more detailed rules.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" alignright size-full wp-image-5324\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/10\/hierarchy-73335_640.jpg\" alt=\"hierarchy 73335 640\" width=\"400\" height=\"248\" style=\"float: right;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/10\/hierarchy-73335_640.jpg 640w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/10\/hierarchy-73335_640-300x186.jpg 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/p>\n<h2>Class hierarchy rule summary:<\/h2>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-domain\">C.120: Use class hierarchies to represent concepts with inherent hierarchical structure (only)<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-abstract\">C.121: If a base class is used as an interface, make it a pure abstract class<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-separation\">C.122: Use abstract classes as interfaces when complete separation of interface and implementation is needed<\/a><\/li>\n<\/ul>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-domain\">C.120: Use class hierarchies to represent concepts with inherent hierarchical structure (only)<\/a><\/h3>\n<p>This is quite obvious. You should use a hierarchy if you model something in the code with an inherently hierarchical structure. The easiest way to reason about my code is if I have a natural match between the code and the world.<\/p>\n<p>For example, I had to model a complex system. This system was a family of defibrillators that consisted of a lot of subsystems. For example, one subsystem was the user interface. The requirement was that the defibrillators should use different user interfaces such as a keyboard, a touch screen, or a few buttons. This system of subsystems was inherently hierarchical; therefore, I modeled it hierarchically. The great benefit was that the software was relatively easy to explain top-down because there was this natural match between the actual hardware and the software.<\/p>\n<p>But, of course, the classic example of using a hierarchy in the design of a graphical user interface (GUI). This is the example the C++ core guidelines are using.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">DrawableUIElement<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n  <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> render() <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">AbstractButton<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> DrawableUIElement {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n  <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> onClick() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">PushButton<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> AbstractButton {\r\n  <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> render() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override;\r\n  <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> onClick() override;\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Checkbox<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> AbstractButton {\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>If something is not inherently hierarchical, you should not model it hierarchically. Have a look here.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">template<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">typename<\/span> T<span style=\"color: #555555;\">&gt;<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Container<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ list operations:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> T<span style=\"color: #555555;\">&amp;<\/span> get() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> put(T<span style=\"color: #555555;\">&amp;<\/span>) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> insert(Position) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ vector operations:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> T<span style=\"color: #555555;\">&amp;<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span>[](<span style=\"color: #007788; font-weight: bold;\">int<\/span>) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> sort() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ tree operations:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> balance() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Why is the example terrible? You have only to read the comments. The class template <span style=\"font-family: courier new,courier;\">Container<\/span> consists of pure virtual functions for modeling a list, a vector, and a tree. If you use Container as an interface, you must implement three disjunct concepts.<\/p>\n<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-abstract\">C.121: If a base class is used as an interface, make it a pure abstract class<\/a><\/h3>\n<p>An abstract class is a class that has at least one pure virtual function. A pure virtual function (<span style=\"font-family: Courier New,Courier,monospace;\">virtual void function() = 0<\/span> ) is a function that a derived class must implement if that class should not be abstract.<\/p>\n<p>Only for completeness reasons. An abstract class can provide implementations of pure virtual functions. A derived class can, therefore, use these implementations.<\/p>\n<p>Interfaces should usually consist of public pure virtual functions and a default\/empty virtual destructor (<span style=\"font-family: Courier New,Courier,monospace;\">virtual ~My_interface() = default<\/span>).&nbsp; If you don&#8217;t follow the rule, something terrible may happen.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Goof<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ...only pure virtual functions here ...<\/span>\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ no virtual destructor<\/span>\r\n};\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Derived<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Goof {\r\nstring s;\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">use<\/span>()\r\n{\r\n  unique_ptr<span style=\"color: #555555;\">&lt;<\/span>Goof<span style=\"color: #555555;\">&gt;<\/span> p {<span style=\"color: #006699; font-weight: bold;\">new<\/span> Derived{<span style=\"color: #cc3300;\">\"here we go\"<\/span>}};\r\n  f(p.get()); <span style=\"color: #0099ff; font-style: italic;\">\/\/ use Derived through the Goof interface <\/span>\r\n} <span style=\"color: #0099ff; font-style: italic;\">\/\/ leak<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p style=\"margin: 0; line-height: 125%;\">If p goes out of scope, it will be destroyed. But Goof has no virtual destructor; therefore, the destructor of <span style=\"font-family: Courier New,Courier,monospace;\">Goof <\/span>and not <span style=\"font-family: Courier New,Courier,monospace;\">Derived <\/span>is called. The harmful effect is that the destructor of the string s is not called.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-separation\">C.122: Use abstract classes as interfaces when complete separation of interface and implementation is needed<\/a><\/h3>\n<p>Abstract classes are about the separation of interface and implementation. You can use a different implementation of <span style=\"font-family: courier new,courier;\">Device<\/span> in the following example during runtime because you only depend on the interface.<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">struct<\/span> Device {\r\n  <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> write(span<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">&gt;<\/span> outbuf) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n  <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> read(span<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">&gt;<\/span> inbuf) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n};\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">D1<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Device {\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ... data ...<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> write(span<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">&gt;<\/span> outbuf) override;\r\n  <span style=\"color: #007788; font-weight: bold;\">void<\/span> read(span<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">&gt;<\/span> inbuf) override;\r\n};\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">D2<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Device {\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ ... different data ...<\/span>\r\n  <span style=\"color: #007788; font-weight: bold;\">void<\/span> write(span<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">&gt;<\/span> outbuf) override;\r\n  <span style=\"color: #007788; font-weight: bold;\">void<\/span> read(span<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">&gt;<\/span> inbuf) override;\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In my seminars to design patterns, I often call this rule the meta-design pattern that is the base for a lot of the design patterns from the most influential software book: <a href=\"https:\/\/en.wikipedia.org\/wiki\/Design_Patterns\"><b>Design Patterns: Elements of Reusable Object-Oriented Software.<\/b><\/a><\/p>\n<h2>Designing rules for classes in a hierarchy summary:<\/h2>\n<p>Here are the more detailed rules in summary. The guidelines have 15 of them.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-abstract-ctor\">C.126: An abstract class typically doesn\u2019t need a constructor<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-dtor\">C.127: A class with a virtual function should have a virtual or protected destructor<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-override\">C.128: Virtual functions should specify exactly one of <code class=\"highlighter-rouge no-highlight\">virtual<\/code>, <code class=\"highlighter-rouge no-highlight\">override<\/code>, or <code class=\"highlighter-rouge no-highlight\">final<\/code><\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-kind\">C.129: When designing a class hierarchy, distinguish between implementation inheritance and interface inheritance<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-copy\">C.130: Redefine or prohibit copying for a base class; prefer a virtual <code class=\"highlighter-rouge no-highlight\">clone<\/code> function instead<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-get\">C.131: Avoid trivial getters and setters<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-virtual\">C.132: Don\u2019t make a function <code class=\"highlighter-rouge no-highlight\">virtual<\/code> without reason<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-protected\">C.133: Avoid <code class=\"highlighter-rouge no-highlight\">protected<\/code> data<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-public\">C.134: Ensure all non-<code class=\"highlighter-rouge no-highlight\">const<\/code> data members have the same access level<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-mi-interface\">C.135: Use multiple inheritance to represent multiple distinct interfaces<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-mi-implementation\">C.136: Use multiple inheritance to represent the union of implementation attributes<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-vbase\">C.137: Use <code class=\"highlighter-rouge no-highlight\">virtual<\/code> bases to avoid overly general base classes<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-using\">C.138: Create an overload set for a derived class and its bases with <code class=\"highlighter-rouge no-highlight\">using<\/code><\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-final\">C.139: Use <code class=\"highlighter-rouge no-highlight\">final<\/code> sparingly<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-virtual-default-arg\">C.140: Do not provide different default arguments for a virtual function and an overrider<\/a><\/li>\n<\/ul>\n<p>Today I write about the first three.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-abstract-ctor\">C.126: An abstract class typically doesn\u2019t need a constructor<\/a><\/h3>\n<p>An abstract class typically has no data and needs no constructor to initialize them.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-dtor\">C.127: A class with a virtual function should have a virtual or protected destructor<\/a><\/h3>\n<p>A class with a virtual function is mainly used via a pointer or a reference to the base. Suppose you explicitly delete the derived class via a pointer, a reference to the base, or indirectly via a smart pointer. In that case, you want to be sure that the derived class&#8217;s destructor is also called. This rule is similar to rule C.121, which discusses pure virtual functions.<\/p>\n<p>Another way to solve the destruction issue is to have a protected and non-virtual base class destructor. This destructor guarantees you can not delete a derived object via a pointer or reference to the base.<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-override\">C.128: Virtual functions should specify exactly one of <code class=\"highlighter-rouge no-highlight\">virtual<\/code>, <code class=\"highlighter-rouge no-highlight\">override<\/code>, or <code class=\"highlighter-rouge no-highlight\">final<\/code><\/a><\/h3>\n<p>&nbsp;In C++11, we have three keywords to deal with overriding.<\/p>\n<ul>\n<li><strong><span style=\"font-family: courier new,courier;\">virtual<\/span><\/strong>: declares a function that can be overwritten in derived classes<\/li>\n<li><strong><span style=\"font-family: courier new,courier;\">override<\/span><\/strong>: ensures that the function is virtual and overwrites a virtual function of a base class<\/li>\n<li><span style=\"font-family: courier new,courier;\"><strong>final:<\/strong><\/span> ensures that the function is virtual and cannot be overridden by a derived class<\/li>\n<\/ul>\n<p>According to the guidelines, the rules for the usage of the three keywords are straightforward: &#8220;Use <code class=\"highlighter-rouge no-highlight\">virtual<\/code> only when declaring a new virtual function. Use <code class=\"highlighter-rouge no-highlight\">override<\/code> only when declaring an override. Use <code class=\"highlighter-rouge no-highlight\">final<\/code> only when declaring a final override.&#8221;<\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">struct<\/span> Base{\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> testGood(){}\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> testBad(){}\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Derived<span style=\"color: #555555;\">:<\/span> Base{\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> testGood() final {}\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> testBad() final override {}\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n    Derived d;\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The method <span style=\"font-family: courier new,courier;\">testBad<\/span>() in the class <span style=\"font-family: courier new,courier;\">Derived<\/span> has a lot of redundant information.<\/p>\n<ul>\n<li>You should only use <span style=\"font-family: courier new,courier;\">final<\/span> or <span style=\"font-family: courier new,courier;\">override<\/span>, if the function is virtual. Skip <span style=\"font-family: courier new,courier;\">virtual<\/span>:&nbsp; <span style=\"font-family: courier new,courier;\">void testBad() final override{}<\/span><\/li>\n<li>Using the keyword <span style=\"font-family: courier new,courier;\">final<\/span> without the <span style=\"font-family: courier new,courier;\">virtual<\/span> keyword is only valid if the function is already virtual; therefore, the function must override a virtual function of a base class. Skip <span style=\"font-family: courier new,courier;\">override<\/span>: <span style=\"font-family: courier new,courier;\">void testBad() final {}<\/span><\/li>\n<\/ul>\n<h2>What&#8217;s next?<\/h2>\n<p>The remaining twelve rules for class hierarchies are missing. My <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-more-rules-to-class-hierarchies\">next post<\/a> will close this gap.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s talk in this post about rules for class hierarchies in general and in particular. The C++ core guidelines have about thirty rules; therefore, I have a lot to discuss.<\/p>\n","protected":false},"author":21,"featured_media":5324,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[502,499],"class_list":["post-5325","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-class-hierarchies","tag-classes"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5325","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5325"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5325\/revisions"}],"predecessor-version":[{"id":6857,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5325\/revisions\/6857"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5324"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}