Changing variables through return value?

Jan 3, 2017 at 8:57pm
Just confirming that my thought process on this is correct.

Below is a wiki sample code from : http://www.cplusplus.com/doc/tutorial/templates/

By stating foo.get() = 15; we are setting the return value of x to = 15
therefore setting x in the private section of the class to = 15

Correct? I did not know you could change variable values by modifying return values. Are there examples of where this is applied/useful?

I can see how it can be detrimental to not use const for getter functions. Though I cant see much benefit to modifying private members of a class through return values rather than constructors/ member functions. I have a few ideas, but they seem impracticle in application.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  // overloading members on constness
#include <iostream>
using namespace std;

class MyClass {
    int x;
  public:
    MyClass(int val) : x(val) {}
    const int& get() const {return x;}
    int& get() {return x;}
};

int main() {
  MyClass foo (10);
  const MyClass bar (20);
  foo.get() = 15;         // ok: get() returns int&
// bar.get() = 25;        // not valid: get() returns const int&
  cout << foo.get() << '\n';
  cout << bar.get() << '\n';

  return 0;
}
Jan 3, 2017 at 10:46pm
Jan 4, 2017 at 3:19am
modifying private members of a class through return value
... and it would be considered bad class design.

See here for a related discussion: http://stackoverflow.com/questions/27209848/changing-a-members-variable-value-inside-another-classes-function
Jan 4, 2017 at 4:05am
would be considered bad class design.

Not necessarily.

It allows for method chaining --- the canonical example is that of std::ostream::operator<<() (which returns a mutable reference to *this), or most examples of operator[]() you've seen.
Last edited on Jan 4, 2017 at 4:06am
Jan 4, 2017 at 4:40am
To *this, yes, but to a private data member as the quoted section was about?
Jan 4, 2017 at 4:52am
> modifying private members of a class through return value
>> ... would be considered bad class design.

If and only if
a. the class has an invariant which restricts the values that the member can hold
and b. the interface allows unrestricted modifications to the member
Jan 4, 2017 at 5:03am
closed account (48T7M4Gy)
Maybe part of the problem/solution is to give the 'offending' get() a better name. Maybe calling it 'setX()' would be good interface design, albeit that it can be chained and all the rest.

There's no great significance in the name as we all know, just conventional wisdom and a low key warning.
Jan 4, 2017 at 7:50am
To *this, yes, but to a private data member as the quoted section was about?
It's indirect, but *this is an interface to std::ostream's private members!

It doesn't necessarily allow unrestricted modifications directly to all its' private members, but that's a good thing. See @JLBorges' post above.
Last edited on Jan 4, 2017 at 7:50am
Jan 4, 2017 at 6:06pm
It's indirect, but *this is an interface to std::ostream's private members!
1
2
std::ostream foo;
std::ostream & bar = foo;

You do claim that bar is more of an interface to foo than foo itself?
Jan 4, 2017 at 6:31pm
You do claim that bar is more of an interface to foo than foo itself?

No, I didn't mean to.

Both the reference and the referent are interfaces to the same object. There's not any difference between the interface provided by foo vs. bar, since they both can be used to modify the same object with the same restrictions.

In other words a reference is transparent to the interface of its' referent.

Maybe my point wasn't clear: there's nothing inherently bad about "modifying private members of a class through a return value", as long as all the invariants are satisfied.
One point is that this statement doesn't imply returning a reference. Here's a contrived example:
Invariant: x can never decrease.

1
2
3
4
5
6
7
8
9
10
class Foo { 
  int x = 0;
public:
  auto make_increment() { 
    return [&] (int const increment_by) { 
      return x += (increment_by > 0)? increment_by: 0; 
    };
  } 
  int get_x() const { return x; } 
};


Definitely Foo::make_incrementr() allows you to modify a private member of *this through its' return value, but you can't violate the class's invariant using that interface.
Last edited on Jan 6, 2017 at 9:10pm
Topic archived. No new replies allowed.