Should you pass member variables within member functions?
Asked Answered
K

3

8

Sort of a style question here. Say I have a class A which has to do a sequence of reasonably complex things to its member variable B b

class A {
 public:
  void DoStuffOnB(){
   DoThing1();
   DoThing2();
   DoThing3();
  }
 private:
  B b;
  void DoThing1(){ /* modify b */ }
  void DoThing2(){ /* modify b */ }
  void DoThing3(){ /* modify b */ }
};

where the DoThings functions only depend on b (or other member variables and some passed parameters). If I want to make those functions re-usable in the future outside of that class, I'm better off writing them as:

class A {
 public:
  void DoStuffOnB(){
   DoThing1(b);
   DoThing2(b);
   DoThing3(b);
  }
 private:
  B b;
  void DoThing1(B& b){ /* modify b */ }
  void DoThing2(B& b){ /* modify b */ }
  void DoThing3(B& b){ /* modify b */ }
};

and then my DoThing functions can just be copied elsewhere in the future. Am I better off writing the function to take all relevant parameters like that, or should the function only take non-member parameters?

In case the answer is "you should write the function to take all relevant parameters", why would one bother to put it in a class?

When should you use a free function, and when should you use a member function?

Kujawa answered 12/8, 2014 at 23:4 Comment(12)
If the functions operate exclusively on the data in the B object then why would they even be a part of the A class? Why not make them free functions (or part of the B type)? Then you could call them from within A or outside of A.Susette
Are any other methods dependent on b? Is it possible to pass b to DoSTuffOnB() rather than store it as a member variable at all?Vicenta
I think it makes sense for A to store b here. The larger scope of what I'm doing is some fairly involved initialization on the member variables of A based on some input.Kujawa
It makes sense for A to store a member variable b, but the DoThingN() methods only operate on b, so they should be either free functions or member functions of class B, and you should be invoking b.DoThing1(), etc, inside your code for A. Then you automatically pass the b element to the functions, of course, but it is done behind the scenes.Homeroom
rather than DoThing1(b), I would write it as b.doThing1(); In general I find it best to have classes manipulate themselves rather than manipulating them externally.Postgraduate
@DaveS: That philosophy will lead to monstrous classes with hundreds or thousands of member functions. Member functions should, for the most part, be reserved for operations that can't be done without access to class internals.Shambles
I should add A would have several instances of B that need to be modified. In general there are a bunch of member variables in A that need initializing.Kujawa
@Benjamin Lindley I'm not sure what you mean by that. If you want organized data to manipulate use a struct, arrays, etc. If you want an encapsulated black-boxed object use a class. If you want to manipulate the object itself you use should use member functions. Class A can have the B variable as part of it and the DoStuffOnB() function, but it makes sense that functions that manipulate the B object directly are part of B's class. This becomes important with maintaining states, you don't want the B object to not know its own state because the A class manipulated its member variables.Postgraduate
@DaveS: "but it makes sense that functions that manipulate the B object directly are part of B's class" -- If, by manipulate directly, you mean tampering with private members, then I agree. But when I saw the comment /* modify b */ in the OP's code, I did not assume that meant tampering with private members, but rather, calling non-const public member functions on b.Shambles
@BenjaminLindley you assumed correctly. In this case b is a simple data structure.Kujawa
Eh, What I'm getting at is that I agree with cdhowie and Jonathan Leffler, make the functions that modify B useful by being able to re-use them outside of A. I prefer to do this by including them as part of the class. If the simple data structure is useful for a certain thing I don't know why you would import a second file containing the free functions when they can be part of the class. In good design the function should only be written once regardless of where you put it, so I don't see how that would bloat the code any.Postgraduate
Here's an article by Scott Meyers about encapsulation and non-member functions: drdobbs.com/cpp/how-non-member-functions-improve-encapsu/…Castled
E
3

Assuming from the context that the "do something on B" functions only operate on the B member and not other state in A then:

  • If the functions directly manipulate/operate on the private state of B then they should be members of B.
  • Else they should be free functions.
Ehlke answered 12/8, 2014 at 23:59 Comment(0)
P
1

A member function is a member function because its' scope has access to the member variables without having to use referencing and pointer syntax. As someone mentioned earlier this would most likely make it simpler to code and maintain so you would use this method unless you needed the function to be a free function that might take the same type data but from different classes in which case you would have to pass by reference or use pointers to gain access to the scope of the variable.

Pedicure answered 7/11, 2017 at 12:15 Comment(0)
C
0

Should you pass member variables within member functions?

There is no need to pass member variables to member functions, since the member functions have access to all the data members.

It's similar to free standing functions accessing static file local variables. The functions have access to the statically declared variables in the same translation unit.

When should you use a freestanding function and when should you use a member function?

In general, use a member function when the functionality is associated with the object.

Use a freestanding function when

  • the class has static members

  • or functionality is associated with a class and doesn't use static members.

You can also use freestanding functions when the same functionality can apply to different objects.
For example, let's talk serialization or outputting of an object.

One can define a method, load_from_buffer() in an object, but it won't work with POD types.

However, if a function load_from_buffer() is made freestanding, it can be overloaded for different types, such as int, char, double and with templates, an overload can be made to call objects derived from an interface.

Summary
Prefer to use member methods when they require access to data members of an object. Use static member methods when they access static data members or there is a need for the functionality without an instance of an object (think encapsulation). Freestanding functions also provide the capability of functionality to different objects based on function overloading.

There are no hard rules, just use what you think will be easiest to maintain, assist in correctness and robustness and speed up development.

Just to confuse people, here is an article by Scott Meyers:
How Non-Member functions increase encapsulation

Remember, in order for a free standing function to access data members of an object, the data members must be given public access or the function needs to be a friend of the object. The classic example is overloading the stream operators for a class.

Castled answered 13/8, 2014 at 0:0 Comment(5)
Regarding this: "Prefer to use member methods when they require access to data members of an object." When would a method ever need access to data members of that object? Can't you always pass all needed data members by reference to a free function?Kujawa
Encapsulation. Data Hiding. If one thinks that a function uses member variables of an object, prefer to place the function inside the class. If one passes an object to a freestanding function, the data members must either be public or the freestanding function declared as a friend.Castled
I don't mean pass an object to a freestranding function. I mean pass an object's data member to a free function vs a member function with no arguments.Kujawa
You can always pass an object's data member to a free standing function; sometimes this is required when using legacy code. Pass by reference or by pointer if the parameter will be modified. A member function, with no parameters, can modify an object's members without the need to pass by pointer or pass by reference.Castled
I know. I'm asking which to prefer and why.Kujawa

© 2022 - 2024 — McMap. All rights reserved.