12

My class definition is spread across headers and source files:

// T.hpp

class T {
   public:
      void foo();
};

// T.cpp

void T::foo() {

}

If T::foo needs to make use of some helper function that need be visible only to T, which of the below solutions is best?

1. Private member

// T.hpp

class T {
   public:
      void foo();
   private:
      void helper();
};

// T.cpp

void T::foo() {
    helper();
}

void T::helper() {
}

2. Free function accessible only in class definition's TU

// T.hpp

class T {
   public:
      void foo();
};

// T.cpp

namespace {
    void helper() {}
}

void T::foo() {
    helper();
}

Is there any difference except that with the former I will end up with more functions in the header file?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
NoSenseEtAl
  • 28,205
  • 28
  • 128
  • 277
  • 1
    This makes NoSenseAtAll. Whether you use member functions or free functions has nothing to do with whether you define them in a header or in a source file. – Lightness Races in Orbit Jan 05 '12 at 17:28
  • I meant that if i only implement them in .cpp file I dont need definition in header file. Ofc I can write definition in .h regardless if they are member or not. – NoSenseEtAl Jan 05 '12 at 17:32
  • 1
    I think I understand. Let me know if my edit is invalid. – Lightness Races in Orbit Jan 05 '12 at 17:33
  • 1
    See [How Non-Member Functions Improve Encapsulation](http://drdobbs.com/cpp/184401197). – Georg Fritzsche Jan 05 '12 at 17:34
  • possible duplicate of [When should I prefer non-member non-friend functions to member functions?](http://stackoverflow.com/questions/7821315/when-should-i-prefer-non-member-non-friend-functions-to-member-functions) – Mark B Jan 05 '12 at 17:35
  • Like the first answer says, prefer non-member functions. However, even non-member functions should be declared in the header file. Otherwise your functions become source code order dependednt...which...sucks... – Benj Jan 05 '12 at 17:37
  • 1
    @Benj: No, they don't, if the free function is _only_ visible to and used in that one source file. And you're welcome to declare those "local" functions at the top of the source file. Orthogonal to adding them to the class's public API. – Lightness Races in Orbit Jan 05 '12 at 17:38
  • @Lightness Races in ORbit, yeah, that is what I thought, except I didnt consider namespaces at all – NoSenseEtAl Jan 05 '12 at 17:38
  • 1
    @NoSenseEtAl: Good. I think that this version is vastly clearer than the difficult-to-parse prose. – Lightness Races in Orbit Jan 05 '12 at 17:39

4 Answers4

10

Prefer free, non-friend functions over member functions, because these have less access to class members than member functions, and therefore have less of a chance to introduce bugs.

If the function is completely outside the interface scope then also put it in an unnamed namespace in the implementation file. This will reduce the chance of bugs even further, because other translation units will not be able to call the function.

Another advantage you get with a non-friend in an unnamed namespace is that there's less of a chance you change the header (since there's one less entity in there). Changing a header file often slows down build times considerably, because of the compile-time dependencies. Private or not, you'll probably have a number of translation units depending in terms of compilation on everything in the header.

wilhelmtell
  • 57,473
  • 20
  • 96
  • 131
  • What would I do if my class is a template class and thus implemented in a header file? I would need the "private free function" in the header for the template class to call it, but then it is not private anymore. – SamVanDonut Nov 19 '18 at 08:06
7

Free functions that need access to private members would require friend declarations in the header anyway, so they're probably not better than private member functions.

Functions that don't need private access should be free functions whether they're declared in the header or not.

So if they need access to private members then make them members. Otherwise make them free functions.

Scott Meyers has this algorithm for deciding whether a function f related to a class C should be a member, friend non-member, or non-member non-friend:

http://drdobbs.com/184401197

if (f needs to be virtual)
   make f a member function of C;
else if (f is operator>> or
         operator<<)
   {
   make f a non-member function;
   if (f needs access to non-public
       members of C)
      make f a friend of C;
   }
else if (f needs type conversions
         on its left-most argument)
   {
   make f a non-member function;
   if (f needs access to non-public
       members of C)
      make f a friend of C;
   }
else if (f can be implemented via C's
         public interface)
   make f a non-member function;
else
   make f a member function of C;
bames53
  • 86,085
  • 15
  • 179
  • 244
1

As far as I can tell, you've pretty much got it. There's no difference other than your header file will needlessly grow. You may also be leaking some implementation details in your class's API, though.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
1

yes, there is a difference

if the functions are not parts of the class, it would be better if they are not tied to this particular class:

  • there is a probability you will want to use them in another class, and in this case it will be very easy to move them in some shared place and use in both classes

  • if the function (which could be a free one) takes a thirdparty class as a parameter and if you make it a member function, you must either include another .h file (which has this class definition) or declare this class in your .h file. this means more coupling, which is bad :)

so I would prefer to write them as free ones (maybe in .cpp file in unnamed namespace, if they aren't (and, probably, won't) used in other classes)

Alek86
  • 1,489
  • 3
  • 17
  • 26