0

I am trying to understand const correctness for setter functions of class. I am a student studding OOP in C++. I (I think) understand the use of const in getter functions, but I get confused in setter functions.

class {
 private:
  int value;
 public:
  int getValue () const { 
    // I understand use of const here prevents the member values from being modified
   return value;
  }
  void setValue (const int val) { 
    /* I get confused here as I used to believe that use of const here 
    was part of const correctness and it prevented the value being passed 
    from being modified inside the function */
   value = val;
  }
};

I want to understand what is the best practice following the principles of const correctness. I have searched online but failed to understand

  1. should const keyword be used in setter functions
  2. if yes, what is the best practice.

My answer might lie here or here but for the love of all that's good I failed to understand the solution.

  • 1
    It stops you doing `val = 42;` by accident. And the line in the 2nd function should be `value = val ;` - typo? – Richard Critten Jul 15 '23 at 20:01
  • The answers to the first question seem pretty clear to me. Is there anything in particular you had a hard time understanding about them? – Nathan Pierson Jul 15 '23 at 20:07
  • When you pass by value there is usually little harm to non `const` parameters because the function's operating on a copy, but when it does matter... Hoo boy. Could save you from a lot of bug hunting. – user4581301 Jul 15 '23 at 20:08
  • IMHO, the setter function should pass by const reference. That's where the `const` comes into play. The setter will not modify the parameter, thus the `const` in the parameter declaration. – Thomas Matthews Jul 15 '23 at 20:10
  • `void setValue(const int val)` is the exact same signature as `void setValue(int val)`. Applying const at toplevel to the parameter itself doesn't change the signature. (Important note: Adding/removing `const` to a type a pointer or a reference points to does change the signature though; the same for adding/removing `const` in a template parameter.) The only difference is the way the parameter is treated inside the function body. – fabian Jul 16 '23 at 08:24

1 Answers1

0

Your understanding of the const keyword on the getter is correct! One caveat here is that it could modify member variables if they are marked as mutable and you may want this if you want logical const and not bitwise const. Logical const means this function call will not change the behavior of the program but it can still modify mutable members (perhaps you are modifying a lastUpdated variable or a counter that needs to be updated each time the function is called). Bitwise const is the default and that's what you described (it can't modify any of the member variables).

For functions that take in arguments (your setter in this example), if they do not need to modify the value then it should be passed in as const. Const here means the object passed in cannot be changed. In this case though, you are passing an integer by value so the function will have it's own copy of the variable and not the original int variable from the call site so it cannot modify the original variable. Since it's a copy it doesn't matter if it's const or not (in terms of modifying the original variable). If this was passed in by pointer or by reference then you would most definitely want to pass it in by const in that case (unless of course you also intended on modifying the passed in parameter).

It is also valid to want to use const on pass by value as well, just be consistent and follow the coding standards at the company you work for. If you don't have a standard for this in place, recommend one and stick to it.

Also note that these 2 function declarations are identical so don't try adding both of these in your header file:

void setValue (int val);
void setValue (const int val);

The const here is redundant and should be left out in the header file as it would only confuse the readers of the header file (both of these setters are const correct since they cannot modify the val parameter). But within your implementation of the function in the .cpp it can make perfect sense to put the const in there (even though it's not needed for const correctness). It can stop accidental bugs such as doing:

 if (p = 2) {} 

instead of the equivalent check:

 if (p == 2) {} 

If p was passed as const int we would've caught this. So yeah its a common standard to leave the const off in the header file but you can keep it in the implementation. This recommendation actually comes from a popular book called C++ Coding Standards by Herb Sutter and Andrei Alexandrescu, definitely check it out some time for some more best practices!

jmbauerful
  • 34
  • 8
  • So, From this, I understand that It really depends on what type of data structure I am passing (assuming the setter function is a simple function only to set member = passed_val;) say I am passing an int I can just make a copy and pass it as it is, but if I am using a larger data structure say a string or an object of a class with lots of member variables being passed by reference (to save memory) I should use const. However, IMHO, const should always be used in the parameter list for a setter function to make sure that the value being passed is never changed in any way. (verbose approach). – Inshal Yousaf Jul 16 '23 at 09:48
  • PS: thanks for explaining bitwise const and Logical const I didn't know that two different types even existed – Inshal Yousaf Jul 16 '23 at 09:50
  • @InshalYousaf • in modern C++, `const` also implies thread-safety. If you have a `mutable` member variable that gets set in a const getter (logical const, rather than bitwise const), it ought also be made thread-safe. Perhaps not important for a (single-threaded) toy program, but becomes important for larger multi-threaded programs. Where "important" means saving you from franctically re-architecting the program. – Eljay Jul 16 '23 at 11:55
  • @InshalYousaf yeah that's all correct! Also your opinion of using const in the parameter list for setters on ints is also a valid opinion. I updated my answer to expand more on this because the comment I drafted went over the character limit :) – jmbauerful Jul 16 '23 at 23:36
  • 1
    @jmbauerful Thank you, you have been a MAJOR help. Also thank you for the invaluable advice. Also thanks to everyone else who gave suggestions and help me understand the problem and related topics. – Inshal Yousaf Jul 18 '23 at 13:55