{"id":5328,"date":"2017-10-13T19:28:33","date_gmt":"2017-10-13T19:28:33","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-more-rules-to-class-hierarchies\/"},"modified":"2023-06-26T12:04:37","modified_gmt":"2023-06-26T12:04:37","slug":"c-core-guidelines-more-rules-to-class-hierarchies","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-more-rules-to-class-hierarchies\/","title":{"rendered":"C++ Core Guidelines: More Rules about Class Hierarchies"},"content":{"rendered":"<p>In the last post, I started our journey with the rules of class hierarchies in modern C++. The first rules had a pretty general focus. This time, I will continue our journey. Now, the rules have a closer focus.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;Here are the rules for class hierarchies.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" alignright size-full wp-image-5326\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/10\/hierarchy.png\" alt=\"\" width=\"400\" height=\"263\" style=\"float: right;\" data-alt=\"hierarchy\" \/><\/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>Let&#8217;s continue with the fourth one.<\/p>\n<h3><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><\/h3>\n<p>At first, what is the difference between implementation inheritance and interface inheritance? The guidelines give a definite answer. Let me cite it.<\/p>\n<ul>\n<li><strong>interface inheritance<\/strong> is the use of inheritance to separate users from implementations, in particular, to allow derived classes to be added and changed without affecting the users of base classes.<\/li>\n<li><strong>implementation inheritance<\/strong> is the use of inheritance to simplify the implementation of new facilities by making useful operations available for implementers of related new operations (sometimes called \u201cprogramming by difference\u201d).<\/li>\n<\/ul>\n<p>Pure interface inheritance will occur if your interface class only has pure virtual functions. In contrast, you have an implementation inheritance if your base class has data members or implemented functions. The guidelines give an example of mixing both concepts.&nbsp;<\/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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Shape<\/span> {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ BAD, mixed interface and implementation<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    Shape();\r\n    Shape(Point ce <span style=\"color: #555555;\">=<\/span> {<span style=\"color: #ff6600;\">0<\/span>, <span style=\"color: #ff6600;\">0<\/span>}, Color co <span style=\"color: #555555;\">=<\/span> none)<span style=\"color: #555555;\">:<\/span> cent{ce}, col {co} { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span>}\r\n\r\n    Point center() <span style=\"color: #006699; font-weight: bold;\">const<\/span> { <span style=\"color: #006699; font-weight: bold;\">return<\/span> cent; }\r\n    Color color() <span style=\"color: #006699; font-weight: bold;\">const<\/span> { <span style=\"color: #006699; font-weight: bold;\">return<\/span> col; }\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> rotate(<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> <span style=\"color: #cc00ff;\">move<\/span>(Point p) { cent <span style=\"color: #555555;\">=<\/span> p; redraw(); }\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">redraw<\/span>();\r\n\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    Point cent;\r\n    Color col;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Circle<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Shape {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    Circle(Point c, <span style=\"color: #007788; font-weight: bold;\">int<\/span> r) <span style=\"color: #555555;\">:<\/span>Shape{c}, rad{r} { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }\r\n\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n<span style=\"color: #9999ff;\">private:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> rad;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Triangle<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public<\/span> Shape {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    Triangle(Point p1, Point p2, Point p3); <span style=\"color: #0099ff; font-style: italic;\">\/\/ calculate center<\/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 class <span style=\"font-family: courier new,courier;\">Shape<\/span> bad?<\/p>\n<ul>\n<li>The more the class grows, the more difficult and error-prone it may become to maintain the various constructors.<\/li>\n<li>The functions of the <span style=\"font-family: courier new,courier;\">Shape<\/span> class may never be used.<\/li>\n<li>If you add data to the <span style=\"font-family: courier new,courier;\">Shape<\/span> class, a recompilation may become probable.<\/li>\n<\/ul>\n<p><span style=\"font-family: courier new, courier;\">Shape<\/span> wouldn&#8217;t need a constructor if it were a pure interface consisting only of pure virtual functions. Of course, with a pure interface, you must implement all functionality in the derived classes.<\/p>\n<p>How can we get the best of two worlds: stable interfaces with interface hierarchies and code reuse with implementation inheritance? One possible answer is dual inheritance. Here is a pretty sophisticated receipt for doing it.<\/p>\n<p><strong>1. Define the base <span style=\"font-family: courier new,courier;\">Shape<\/span> of the class hierarchy as a pure interface<\/strong><\/p>\n<ol>\n<ol><!-- HTML generated using hilite.me --><\/ol>\n<\/ol>\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;\">Shape<\/span> {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ pure interface<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> Point center() <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: #006699; font-weight: bold;\">virtual<\/span> Color color() <span style=\"color: #006699; font-weight: bold;\">const<\/span> <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> rotate(<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> move(Point p) <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n\r\n    <span style=\"color: #006699; font-weight: bold;\">virtual<\/span> <span style=\"color: #007788; font-weight: bold;\">void<\/span> redraw() <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">0<\/span>;\r\n\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><strong>2. Derive a pure interface <span style=\"font-family: courier new,courier;\">Circle<\/span> from the <span style=\"font-family: courier new,courier;\">Shape<\/span><\/strong><\/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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Circle<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public virtual ::<\/span>Shape {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ pure interface<\/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;\">int<\/span> radius() <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><strong>3. Provide the implementation class <span style=\"font-family: courier new,courier;\">Impl::Shape&nbsp;<\/span><\/strong><\/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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Impl<\/span><span style=\"color: #555555;\">::<\/span>Shape <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public virtual<\/span> ::Shape { <span style=\"color: #0099ff; font-style: italic;\">\/\/ implementation<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ constructors, destructor<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n    Point center() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }\r\n    Color color() <span style=\"color: #006699; font-weight: bold;\">const<\/span> override { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }\r\n\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> rotate(<span style=\"color: #007788; font-weight: bold;\">int<\/span>) override { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> move(Point p) override { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }\r\n\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> redraw() override { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }\r\n\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><strong>4. Implement the class <span style=\"font-family: courier new,courier;\">Impl::Circle<\/span> by inheriting from the interface and the implementation<\/strong><\/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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Impl<\/span><span style=\"color: #555555;\">::<\/span>Circle <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public virtual<\/span> ::Circle, <span style=\"color: #006699; font-weight: bold;\">public<\/span> Impl<span style=\"color: #555555;\">::<\/span>Shape {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ implementation<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ constructors, destructor<\/span>\r\n\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> radius() override { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> }\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><strong>5. If you want to extend the class hierarchy, you have to derive from the interface and the implementation&nbsp;<\/strong> <span style=\"font-family: courier new,courier;\"><\/span><\/p>\n<p>The class <span style=\"font-family: courier new,courier;\">Smiley<\/span> is a pure interface derived from <span style=\"font-family: courier new,courier;\">Circle.<\/span> The class<span style=\"font-family: courier new,courier;\"> Impl::Smiley<\/span> is the new implementation, public derived from <span style=\"font-family: courier new,courier;\">Smiley<\/span> and <span style=\"font-family: courier new,courier;\">Impl::Circle<\/span>.<\/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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Smiley<\/span> <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public virtual <\/span>Circle { <span style=\"color: #0099ff; font-style: italic;\">\/\/ pure interface<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Impl<\/span><span style=\"color: #555555;\">::<\/span>Smiley <span style=\"color: #555555;\">:<\/span> <span style=\"color: #006699; font-weight: bold;\">public virtual<\/span> ::Smiley, <span style=\"color: #006699; font-weight: bold;\">public<\/span> Impl<span style=\"color: #555555;\">::<\/span>Circle {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ implementation<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ constructors, destructor<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Here is once more the big picture of the two hierarchies.<\/p>\n<ul>\n<li>interface: <span style=\"font-family: courier new,courier;\">Smiley -&gt; Circle -&gt; Shape<\/span><\/li>\n<li>implementation:<span style=\"font-family: courier new,courier;\"> Impl::Smiley -&gt; Imply::Circle -&gt; Impl::Shape<\/span><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p class=\"r\">By reading the last lines, maybe you had a d\u00e9j\u00e0 vu. You are right. This technique of multiple inheritances is similar to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Adapter_pattern\">adapter pattern,<\/a> implemented with multiple inheritances. The adapter pattern is from the well-known <a href=\"https:\/\/en.wikipedia.org\/wiki\/Design_Patterns\">design pattern<\/a> book.<\/p>\n<p>The idea of the adapter pattern is to translate an interface into another interface. You achieve this by inheriting public from the new interface and private from the old one. That means you use the old interface as an implementation.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5327\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/10\/AdapterrClass.png\" alt=\"AdapterrClass\" width=\"448\" height=\"294\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/10\/AdapterrClass.png 448w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/10\/AdapterrClass-300x197.png 300w\" sizes=\"auto, (max-width: 448px) 100vw, 448px\" \/><\/p>\n<h3><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><\/h3>\n<p>I can make it relatively short. Rule<a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-copy-and-move-rules\"> C.67<\/a> gives a reasonable explanation for this rule.<\/p>\n<\/p>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-get\">C.131: Avoid trivial getters and setters<\/a><\/h3>\n<p>If a trivial getter or setter provides no semantic value, publicize the data item. Here are two examples of trivial getters and setters:<\/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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Point<\/span> {   <span style=\"color: #0099ff; font-style: italic;\">\/\/ Bad: verbose<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> y;\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    Point(<span style=\"color: #007788; font-weight: bold;\">int<\/span> xx, <span style=\"color: #007788; font-weight: bold;\">int<\/span> yy) <span style=\"color: #555555;\">:<\/span> x{xx}, y{yy} { }\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> get_x() <span style=\"color: #006699; font-weight: bold;\">const<\/span> { <span style=\"color: #006699; font-weight: bold;\">return<\/span> x; }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> set_x(<span style=\"color: #007788; font-weight: bold;\">int<\/span> xx) { x <span style=\"color: #555555;\">=<\/span> xx; }\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> get_y() <span style=\"color: #006699; font-weight: bold;\">const<\/span> { <span style=\"color: #006699; font-weight: bold;\">return<\/span> y; }\r\n    <span style=\"color: #007788; font-weight: bold;\">void<\/span> set_y(<span style=\"color: #007788; font-weight: bold;\">int<\/span> yy) { y <span style=\"color: #555555;\">=<\/span> yy; }\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ no behavioral member functions<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">x<\/span> and <span style=\"font-family: courier new,courier;\">y<\/span> can have an arbitrary value. This means an instance of <span style=\"font-family: courier new,courier;\">Point<\/span> maintains no invariant on <span style=\"font-family: courier new,courier;\">x<\/span> and <span style=\"font-family: courier new,courier;\">y. x<\/span> and <span style=\"font-family: courier new,courier;\">y<\/span> are just values. Using a struct as a collection of values is more appropriate.<\/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;\">struct<\/span> Point {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x {<span style=\"color: #ff6600;\">0<\/span>};\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> y {<span style=\"color: #ff6600;\">0<\/span>};\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h3><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><\/h3>\n<p>This is quite obvious. A virtual function is a feature that you will not get for free.<\/p>\n<p>A virtual function<\/p>\n<ul>\n<li>increases the run-time and the object code-size<\/li>\n<li>is open for mistakes because it can be overwritten in derived classes<\/li>\n<\/ul>\n<h3><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rh-protected\">C.133: Avoid <code class=\"highlighter-rouge no-highlight\">protected<\/code> data<\/a><\/h3>\n<p>Protected data make your program complex and error-prone. If you put protected data into a base class, you can not reason about derived classes in isolation and, therefore, you break encapsulation. You always have to reason about the whole class hierarchy.<\/p>\n<p>This means you have to answer at least these three questions.<\/p>\n<ol>\n<li>Do I have to implement a constructor to initialize the protected data?<\/li>\n<li>What is the actual value of the protected data if I use them?<\/li>\n<li>Who will be affected if I modify the protected data?<\/li>\n<\/ol>\n<p>Answering these questions becomes more and more complicated the more extensive your class hierarchy becomes.<\/p>\n<p>If you think about it: protected data is a kind of global data in the scope of the class hierarchy. And you know, non-const global data is terrible.<\/p>\n<p>Here is the interface Shape enriched with protected data.<\/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;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Shape<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ... interface functions ...<\/span>\r\n<span style=\"color: #9999ff;\">protected:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ data for use in derived classes:<\/span>\r\n    Color fill_color;\r\n    Color edge_color;\r\n    Style st;\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<h2>What&#8217;s next<\/h2>\n<p>We are not done with the rules for class hierarchies, and therefore,&nbsp; I will continue with my tour in the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-the-remaining-rules-to-class-hierarchie\">next post<\/a>.<\/p>\n<p><strong>I have to make a personal confession. I learned a lot by paraphrasing the C++ core guidelines rules and providing more background info if that was necessary from my perspective. I hope the same will hold for you. I would be happy to get comments. So, what&#8217;s your opinion?<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the last post, I started our journey with the rules of class hierarchies in modern C++. The first rules had a pretty general focus. This time, I will continue our journey. Now, the rules have a closer focus.<\/p>\n","protected":false},"author":21,"featured_media":5326,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[502,499],"class_list":["post-5328","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\/5328","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=5328"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5328\/revisions"}],"predecessor-version":[{"id":6856,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5328\/revisions\/6856"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5326"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5328"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}