{"id":5303,"date":"2017-08-18T13:27:18","date_gmt":"2017-08-18T13:27:18","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-class-rules\/"},"modified":"2023-06-26T12:08:14","modified_gmt":"2023-06-26T12:08:14","slug":"c-core-guidelines-class-rules","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-class-rules\/","title":{"rendered":"C++ Core Guidelines: Class Rules"},"content":{"rendered":"<p>A class is a user-defined type where the programmer can specify the representation, the operations, and the interface. The C++ core guidelines have a lot of rules for user-defined types.<\/p>\n<p><!--more--><\/p>\n<p>The guidelines start with general rules but also include special rules for constructors and destructors, class hierarchies, overloading of operators, and unions.<\/p>\n<p>Before I write about the special rules that are way more interesting, here are the eight general rules.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-org\">C.1: Organize related data into structures (<code class=\"highlighter-rouge no-highlight\">struct<\/code>s or <code class=\"highlighter-rouge no-highlight\">class<\/code>es)<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-struct\">C.2: Use <code class=\"highlighter-rouge no-highlight\">class<\/code> if the class has an invariant; use <code class=\"highlighter-rouge no-highlight\">struct<\/code> if the data members can vary independently<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-interface\">C.3: Represent the distinction between an interface and an implementation using a class<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-member\">C.4: Make a function a member-only if it needs direct access to the representation of a class<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-helper\">C.5: Place helper functions in the same namespace as the class they support<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-standalone\">C.7: Don\u2019t define a class or enum and declare a variable of its type in the same statement<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-class\">C.8: Use <code class=\"highlighter-rouge no-highlight\">class<\/code> rather than <code class=\"highlighter-rouge no-highlight\">struct<\/code> if any member is non-public<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-private\">C.9: Minimize exposure of members<\/a><\/li>\n<\/ul>\n<p>I will only write as much to the general class rules to make their intention clear.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"General_rules_for_classes\"><\/span>General rules for classes<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5302\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/08\/Observer.png\" alt=\"Observer\" width=\"579\" height=\"220\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/08\/Observer.png 579w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/08\/Observer-300x114.png 300w\" sizes=\"auto, (max-width: 579px) 100vw, 579px\" \/><\/p>\n<h3><span class=\"ez-toc-section\" id=\"C1_Organize_related_data_into_structures_structs_or_classes\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-org\">C.1: Organize related data into structures (<code class=\"highlighter-rouge no-highlight\">struct<\/code>s or <code class=\"highlighter-rouge no-highlight\">class<\/code>es)<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If data is related, you should put it into a struct or class; therefore, the second function is straightforward to comprehend.<\/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: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">draw<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span> x, <span style=\"color: #007788; font-weight: bold;\">int<\/span> y, <span style=\"color: #007788; font-weight: bold;\">int<\/span> x2, <span style=\"color: #007788; font-weight: bold;\">int<\/span> y2);  <span style=\"color: #0099ff; font-style: italic;\">\/\/ BAD: unnecessary implicit relationships<\/span>\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">draw<\/span>(Point from, Point to);          <span style=\"color: #0099ff; font-style: italic;\">\/\/ better<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C2_Use_class_if_the_class_has_an_invariant_use_struct_if_the_data_members_can_vary_independently\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-struct\">C.2: Use <code class=\"highlighter-rouge no-highlight\">class<\/code> if the class has an invariant; use <code class=\"highlighter-rouge no-highlight\">struct<\/code> if the data members can vary independently<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>An invariant is a logical condition that a constructor typically establishes.<\/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> Pair {  <span style=\"color: #0099ff; font-style: italic;\">\/\/ the members can vary independently<\/span>\r\n    string name;\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> volume;\r\n};\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Date<\/span> {\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ validate that {yy, mm, dd} is a valid date and initialize<\/span>\r\n    Date(<span style=\"color: #007788; font-weight: bold;\">int<\/span> yy, Month mm, <span style=\"color: #007788; font-weight: bold;\">char<\/span> dd);\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> y;\r\n    Month m;\r\n    <span style=\"color: #007788; font-weight: bold;\">char<\/span> d;    <span style=\"color: #0099ff; font-style: italic;\">\/\/ day<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The class <span style=\"font-family: courier new,courier;\">Date<\/span> has the invariants<span style=\"font-family: courier new,courier;\"> y<\/span>, <span style=\"font-family: courier new,courier;\">m<\/span>, and <span style=\"font-family: courier new,courier;\">d<\/span>. They are initialized and checked in the constructor. The data type <span style=\"font-family: courier new,courier;\">Pair<\/span> has no invariant; therefore, it is a struct.<\/p>\n<p>Due to the invariance, the class is easier to use. This is precisely the aim of the following rule.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C3_Represent_the_distinction_between_an_interface_and_an_implementation_using_a_class\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-interface\">C.3: Represent the distinction between an interface and an implementation using a class<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The public methods are, in this case, the interface of a class, and the private part is the implementation.<\/p>\n<p>&nbsp;<\/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;\">Date<\/span> {\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ... some representation ...<\/span>\r\n<span style=\"color: #9999ff;\">public:<\/span>\r\n    Date();\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ validate that {yy, mm, dd} is a valid date and initialize<\/span>\r\n    Date(<span style=\"color: #007788; font-weight: bold;\">int<\/span> yy, Month mm, <span style=\"color: #007788; font-weight: bold;\">char<\/span> dd);\r\n\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> day() <span style=\"color: #006699; font-weight: bold;\">const<\/span>;\r\n    Month month() <span style=\"color: #006699; font-weight: bold;\">const<\/span>;\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n};\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>From a maintainability perspective, the implementations of the class <span style=\"font-family: courier new,courier;\">Date<\/span> can be changed without affecting the user.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C4_Make_a_function_a_member-only_if_it_needs_direct_access_to_the_representation_of_a_class\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-member\">C.4: Make a function a member-only if it needs direct access to the representation of a class<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If a function needs no access to the internals of the class, it should not be a member. Hence you get<a href=\"https:\/\/en.wikipedia.org\/wiki\/Loose_coupling\"> loose coupling, <\/a>and a change in the internals of the class will not affect the function.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C5_Place_helper_functions_in_the_same_namespace_as_the_class_they_support\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-helper\">C.5: Place helper functions in the same namespace as the class they support<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Such a helper function should be in the namespace of the class.<\/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;\">namespace<\/span> Chrono { <span style=\"color: #0099ff; font-style: italic;\">\/\/ here we keep time-related services<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\"><\/span><span style=\"color: #00aa88; font-weight: bold;\"><\/span><span style=\"color: #0099ff; font-style: italic;\"><\/span>\r\n    <span style=\"color: #006699; font-weight: bold;\">class<\/span> <span style=\"color: #00aa88; font-weight: bold;\">Date<\/span> { <span style=\"color: #0099ff; font-style: italic;\">\/* ... *\/<\/span> };\r\n\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ helper functions:<\/span>\r\n    <span style=\"color: #007788; font-weight: bold;\">bool<\/span> <span style=\"color: #006699; font-weight: bold;\">operator<\/span><span style=\"color: #555555;\">==<\/span>(Date, Date);\r\n    Date <span style=\"color: #cc00ff;\">next_weekday<\/span>(Date);\r\n    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span>\r\n}<br \/>...<br \/>if (date1 == date2){  ...           \/\/ (1)<br \/>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Thanks to <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/adl\">argument-dependent lookup<\/a> (ADL), the comparison in (1) will additionally look for the identity operator in the <span style=\"font-family: courier new,courier;\">Chrono<\/span> namespace.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C7_Dont_define_a_class_or_enum_and_declare_a_variable_of_its_type_in_the_same_statement\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-standalone\">C.7: Don\u2019t define a class or enum and declare a variable of its type in the same statement<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>I admit: defining a class and declaring a variable of its type in the same statement confuses me.<\/p>\n<p>&nbsp;<\/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: #0099ff; font-style: italic;\">\/\/ bad<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Data { <span style=\"color: #0099ff; font-style: italic;\">\/*...*\/<\/span> } data{ <span style=\"color: #0099ff; font-style: italic;\">\/*...*\/<\/span> }; \r\n\r\n<span style=\"color: #0099ff; font-style: italic;\">\/\/ good<\/span>\r\n<span style=\"color: #006699; font-weight: bold;\">struct<\/span> Data { <span style=\"color: #0099ff; font-style: italic;\">\/*...*\/<\/span> };         \r\nData data{ <span style=\"color: #0099ff; font-style: italic;\">\/*...*\/<\/span> };\r\n<\/pre>\n<\/div>\n<h3><span class=\"ez-toc-section\" id=\"C8_Use_class_rather_than_struct_if_any_member_is_non-public\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-class\">C.8: Use <code class=\"highlighter-rouge no-highlight\">class<\/code> rather than <code class=\"highlighter-rouge no-highlight\">struct<\/code> if any member is non-public<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>This is quite a valid and often-used convention. If a data type has private or protected members, make it a class.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C9_Minimize_exposure_of_members\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-private\">C.9: Minimize exposure of members<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>This rule, also called data hiding, is one of the cornerstones of object-oriented class design. It means that you should think about two interfaces for your class. A public interface for the general use case and a protected interface for derived classes. The remaining members should be private.<\/p>\n<p>I will continue with the more special rules. Here is an overview:<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-concrete\">C.concrete: Concrete types<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#S-ctor\">C.ctor: Constructors, assignments, and destructors<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-containers\">C.con: Containers and other resource handles<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-lambdas\">C.lambdas: Function objects and lambdas<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-hier\">C.hier: Class hierarchies (OOP)<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-overload\">C.over: Overloading and overloaded operators<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#SS-union\">C.union: Unions<\/a><\/li>\n<\/ul>\n<p>Let&#8217;s continue with the two rules to concrete types.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Concrete_types\"><\/span>Concrete types<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-concrete\">C.10: Prefer concrete types over class hierarchies<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-regular\">C.11: Make concrete types regular<\/a><\/li>\n<\/ul>\n<p>First of all, I have to write about concrete types and regular types.<\/p>\n<p>A <strong>concrete type<\/strong> is &#8220;the simplest kind of a class&#8221;. It is often called a value type and is not part of a type hierarchy. Of course, an abstract type can not be concrete.<\/p>\n<p>A<strong> regular type<\/strong> is a type that &#8220;behaves like an int&#8221; and has, therefore, to support copy and assignment, equality, and order. To be more formal. A regular type <span style=\"font-family: courier new,courier;\">Regular<\/span> supports the following operations.<\/p>\n<ul>\n<li>&nbsp;Copy and assignment\n<ul><!-- HTML generated using hilite.me --><\/ul>\n<\/li>\n<\/ul>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%; padding-left: 90px;\">Regular a;\r\nRegular a  <span style=\"color: #555555;\">=<\/span> b;\r\n<span style=\"color: #555555;\">~<\/span>Regular(a);\r\na <span style=\"color: #555555;\">=<\/span> b;\r\n<\/pre>\n<\/div>\n<ul>\n<li>Equality<\/li>\n<\/ul>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%; padding-left: 90px;\">a <span style=\"color: #555555;\">==<\/span> b;<br \/>a <span style=\"color: #555555;\">!=<\/span> b;<\/pre>\n<\/div>\n<ul>\n<li>Ordering<\/li>\n<\/ul>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3 none repeat scroll 0% 0%; overflow: auto; width: auto; border-width: 0.1em 0.1em 0.1em 0.8em;\">\n<pre style=\"margin: 0px; line-height: 125%; padding-left: 90px;\">a <span style=\"color: #555555;\">&lt;<\/span> b;<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The built-in types are regular such as the container of the standard template library.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C10_Prefer_concrete_types_over_class_hierarchies\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-concrete\">C.10: Prefer concrete types over class hierarchies<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Use a concrete type if you have no use case for a class hierarchy. A concrete type is way easier to implement, smaller, and faster. You do have not to think about inheritance, virtuality, references, or pointers, including memory allocation and deallocation. There will be no virtual dispatch and, therefore, no runtime overhead.<\/p>\n<p>You have value.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"C11_Make_concrete_types_regular\"><\/span><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Rc-regular\">C.11: Make concrete types regular<\/a><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Regular types (ints) are easier to understand. They are, per see, intuitive. If you have a concrete type think about upgrading it to a regular type.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Whats_next\"><\/span>What&#8217;s next<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-constructors-assignments-and-desctructors\">next post <\/a>will be about the lifetime of objects: create, copy, move, and destroy.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A class is a user-defined type where the programmer can specify the representation, the operations, and the interface. The C++ core guidelines have a lot of rules for user-defined types.<\/p>\n","protected":false},"author":21,"featured_media":5302,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[499],"class_list":["post-5303","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-classes"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5303","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=5303"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5303\/revisions"}],"predecessor-version":[{"id":6864,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5303\/revisions\/6864"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5302"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}