Note that there are some explanatory texts on larger screens.

plurals
  1. POoverloaded const and non-const class methods returning references in C++
    text
    copied!<p>I have a data-structure class in C++ with an accessor to some object (may be large) and I have const and non-const methods using this accessor so I need to overload it. I am looking for a <strong>critique</strong> of the code below - maybe there is a way to accomplish the same thing that is cleaner?</p> <p>The way I understand it, there are two ways to achieve this without duplicating the code in the accessor in the following case, the method get(). I am not sure if there are serious issues with either of these two methods and <strong>I would like some guidance</strong> here.</p> <p>I like method A because:</p> <ul> <li>only one const_cast</li> <li>const-version of the method get() returns a copy</li> <li>the non-const method gets the non-const reference directly</li> </ul> <p>I don't like method A because:</p> <ul> <li>the non-const method get() is const only by contract, (not checked by compiler)</li> <li>harder to get a const-reference, though not impossible</li> </ul> <p>I like method B because:</p> <ul> <li>the const-ness of the const method get() is checked by compiler</li> <li>copy of the returned object is controlled by the user</li> </ul> <p>I don't like method B because:</p> <ul> <li>requires two const_casts which is hard to read</li> </ul> <p>here is the (minimal) example code of the two cases.</p> <pre class="lang-cpp prettyprint-override"><code>/** * summary: * Two classes with an overloaded method which is * guaranteed (by contract) not to change any * internal part of the class. However, there is a * version of this method that will return a non-const * reference to an internal object, allowing the user * to modify it. Don't worry about why I would ever * want to do this, though if you want a real-world * example, think about std::vector&lt;&gt;::front() * * The difference between A and B can be summarized * as follows. In both cases, the second method merely * calls the first, wrapped with the needed * const_cast's * * struct A { * int&amp; get(); * int get() const; * }; * * struct B { * const int&amp; get() const; * int&amp; get(); * }; * **/ struct A { int _val; A() : _val(7) {}; // non-const reference returned here // by a non-const method int&amp; get() { // maybe lots of calculations that you do not // wish to be duplicated in the const version // of this method... return _val; } // const version of get() this time returning // a copy of the object returned int get() const { // CONST-CAST!!?? SURE. return const_cast&lt;A*&gt;(this)-&gt;get(); } // example of const method calling the // overloaded get() method int deep_get() const { // gets a copy and makes // a copy when returned // probably optimized away by compiler return this-&gt;get(); } }; struct B { int _val; B() : _val(7) {}; // const reference returned here // by a const method const int&amp; get() const { // maybe lots of calculations that you do not // wish to be duplicated in the non-const // version of this method... return _val; } // non-const version of get() this time returning // a copy of the object returned int&amp; get() { // CONST-CAST!? TWO OF THEM!!?? WHY NOT... return const_cast&lt;int&amp;&gt;(const_cast&lt;const B*&gt;(this)-&gt;get()); } // example of const method calling the // overloaded get() method int deep_get() const { // gets reference and makes // a copy when returned return this-&gt;get(); } }; int main() { A a; a.get() = 8; // call non-const method a.deep_get(); // indirectly call const method B b; b.get() = 8; // call non-const method b.deep_get(); // indirectly call const method } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload