2

I have read a lot of materials regarding preferring returning values from function like this:

some_class func();

over getting output by passing it by reference like this:

void func(some_class& input);

I have found little information regarding whether similar rule applies to class private member methods though. Suppose I have a class A with members a, b and c, where variables a and b are set via the constructor, and c is calculated based on a and b. One may design such a class in the following ways:

class A
{
    A(const Class1& x, const Class2& y) : a(x), b(y) { outer_funct() };

private:
    // option 1: calculate a in some outer function like this: c = calc_c();
    // a and b values are only read within the method's body:
    Class3 calc_c() const;

    // option 2: calculate a inside calc_c();
    // a and b values are only read within the method's body:
    void calc_c();   

    void outer_funct()
    {
        // option 1:
        c = calc_c();

        // option 2:
        calc_c();
    }

    Class1 a; 
    Class2 b; 
    Class3 c;
};

In reality c would be an object, whose value depends on more than ten member variables - that is why I don't consider having a stand-alone helper function that takes the variables needed for calculating c by const reference.

I am weighing pros and cons of both approaches.

What speaks to me about the option 1 is that it shows my intent, which is that calling calc_c() should result in modyfing only one variable, and const qualifier prevents side effects. On the other hand, writing the method in such a way may make someone think it could be used for setting other member variables of Class3 too, whereas it should only be used to set c - I have doubts whether relying on commenting the functions is a good solution to prevent that.

Option 2 in turn looks appealing beacuse it doesn't mislead the reader in the way described above. On the other hand, there is no syntactic hint regarding which variables should be or should not be modified within this function, so it may be harder to maintain the class invariants and track down bugs.

I'd like to know if there are some other considerations speaking for one of the options that I cannot see. Is it a matter of taste in the end, or is there something more to it that would favor one of the options as "better"?

0

1 Answer 1

2

I'd prefer calling c = calc_c(a,b); or c = calc_c(this) directly from the constructor. I think that would make the intent most clear:

  • all the fields are now visibly being initialized within constructor
  • calc_c (can be a static method that) clearly does not (cannot) mutate an A
  • it is more clear that c cannot be recalculated in the future, useful since a and b are bound by the constructor.
4
  • 1
    Both intent and side-effects of calling calc_c are most clear with the first option: c = calc_c(a,b). The more your intent and side-effects are known, the less likely you are to introduce careless bugs. Commented Sep 1, 2017 at 17:43
  • Thanks for the replies. The thing is, as I've written in the question description, actually there might be e.g. more than 10 arguments, and I have multiple methods that this dilemma refers to, so it seems painful to pass so many arguments multiple times, and that's why I've ruled this option out.
    – KjMag
    Commented Sep 2, 2017 at 20:38
  • @KjMag You could always pass in a struct containing the arguments to reduce the number. A reader has to go one more step - they need to read the definition of the structure, but it's at least still explicitly stating your intent. Commented Sep 2, 2017 at 23:57
  • @user1118321 That's a good idea when you are passing exactly the same arguments each time, but I pass them in different configurations depending on function.
    – KjMag
    Commented Sep 9, 2017 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.