简体   繁体   中英

C++ Private Functions: Whether to pass class member variable by function parameter, or not

Here's a question that comes up again and again in C++ class implementation. I'm curious about what people's thoughts are here. Which code do you prefer and why?

class A
{
public:
    /* Constructors, Destructors, Public interface functions, etc. */ 
    void publicCall(void);

private:
    void f(void);

    CMyClass m_Member1;
};

with

void A::publicCall(void)
{
    f();
}

void A::f(void)
{
    // do some stuff populating  m_Member1
}

Or the alternative:

class A
{
public:
    /* Constructors, Destructors, Public interface functions, etc. */ 
    void publicCall(void);

private:
    void f(CMyClass &x);

    CMyClass m_Member1;
};

with

void A::publicCall(void)
{
    f(m_Member1);
}

void A::f(CMyClass &x)
{
    // do some stuff to populate x, 
    // locally masking the fact that it's really m_Member1
}

I think I always prefer the second one because then f can then operate on any instance of CMyClass but, that said, I have lots of code where the first is perfectly valid since f will only ever operate on m_Member1 and I'm really breaking it into two functions to make the code more readable.

Yes, this is more of a discussion question than an "answer" question, but I'm more interested in the reasoning. I'll mark as an answer a response that gives good reasoning or a good criterion.

Also, keep in mind that this is just a toy example. The class will be bigger than this in reality and thus organization is important.

Since you're asking for opinions, if a standalone f(CMyClass&) function makes sense and is implementable, then I would also favour that option. I would opt for the first case if the operation performed by f only makes sense in the context of class A, if CMyClass only makes sense in A's context, or if it depends on other attributes of A . I think one has have to decide depending on the problem.

As always, that depends. Each scenario is different.

In the specific example you gave - first I'd rule out your alternative ( void A::f(CMyClass &x) ) mainly because it 'smells' bad (as Martin Fowler puts it). It's a private function, and unless you need to use it now for other instances, make it use the member. You can always refactor it if the need arises.

Imagine what would happen if f had 2 parameters. 3 parameters. 10. Would it make sense then to send them each time? Wouldn't it be better to have these parameters members?

And what if f had to send some of these arguments to other methods of A ? Doesn't it make more sense to use members for this?

All of this is assuming that f does need other information which A holds, otherwise I'd move it to be a method of CMyClass .

Ask yourself: Does it have any meaning now, or may it have any meaning in the foreseable future, to call f() with an object other than m_Member1 ?

If the answer is:

  • No . Do a parameterless f() as m_Member1 is an intrinsic part of A .
  • Yes . Do the f(CMyClass &) . Even if now you only use m_Member1 , that is not an intrinsic property of the classes you handle.
  • Maybe . Well... I'd say go with the parameterless f() . There is always the option to change your mind (the change if fairly trivial, actually).

Also note that a function f() can call another function g(CMyClass &) , but not the other way around. So, depending on what f() does, that may limit your options.

Isn't f in the second example better of as a static function of A or global function or, maybe, a member function of CMyClass ?

Of course, there are cases where you're better off sending the argument every time you call that function, but why would you resend it when you already have on CMyClass object in the A object. If you need both CMyClass objects to interact, you may be better off adding it to CMyClass member function list, rather than to A .

Also, as Clean Code states, you're better off with functions without any arguments, than with ones with arguments. When another programmer tries to read the function, it must decipher/pay attention to the second parameter, besides the function name.

I would base the answer on the context. If there are now or might some day be multiple instances of member variables that f might operate on, then sure, pass it/them as parameters. However, if f is operating on specific elements of the state of the instance of A, I would not pass anything to it. There are lots of cases where there will always be only one foo in an A. At that point is becomes silly to make foo a parameter to f. And slightly less efficient, unless f is inline, since not only is the this pointer being passed, but also the address of foo, which is an extra copy onto the stack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM