15

After reading sbi and Eli Bendersky's answers in this question I started to wondering what static member functions are for.

A class' friend free function shouldn't be able to do anything a static member function can do? If so, why/when should I prefer a static member function to a friend free one?

Community
  • 1
  • 1
peoro
  • 24,051
  • 18
  • 90
  • 141

5 Answers5

13

In general:

Require access to private members

static member functions have access to private members of the class. If you need that, you can use a static member function. You have to declare it in the header anyway to give it access, so you may as well make it a member rather than a friend. It is commonly done this way for singletons that have a getInstance() method as singleton, and classes that use a static factory method createInstance() to ensure they are created on the heap. Both of these need access to the private constructor.

Meta-programming

static member functions are very good for template meta-programming where you can pass in a class and call its method without knowing at the point of call what function will actually get invoked. This is commonly called "compile-time polymorphism" and is an important part of meta-programming. std::char_traits is based on this principle.

Restricted access

The common use of a private static member function, just so that it can be accessed only by the class, and does not itself need access to private members, is not a good use of static member functions because it is part of the implementation detail of the class, and this is better done in the anonymous namespace of the compilation unit.

However if the static member function is protected it has use as it can get called by derived classes but not by external classes.

friend functions

  • Can have access to private members but need to be declared in the header anyway.
  • Can be used in meta-programming as part of an "overload" however still needs to be declared in the header. (Common example is operator<<)
  • Does not work for protected access with friendship as what you are trying to do here is restrict access to the method, not what the call has access to.
CashCow
  • 29,087
  • 4
  • 53
  • 86
  • In what cases friend free functions can not be used in template meta-programming? Cannot find any example where a templated friend free function won't be able to do something that a static member function can do. The third point is a good one, didn't think of it! – peoro Jan 18 '11 at 11:26
  • traits classes for example. traits_class::dostuff( params ); dostuff being a static member of traits_class. – CashCow Jan 18 '11 at 12:04
  • In the above answer traits_class is a template parameter or derived from a template parameter. – CashCow Jan 18 '11 at 12:19
  • I think this could also be done with free functions (ie: `dostuff< traits_class >( params );`), but it would be worse because `dostuff` isn't in `traits_class` scope. – peoro Jan 18 '11 at 13:43
  • 1
    @peoro: I am not so sure, one advantage of the free functions is that you can easily provide a default version in case the user does not wish to provide the traits. Testing for the present of a static member function within the trait class is more difficult. – Matthieu M. Jan 18 '11 at 16:19
  • Yes, you can of course create a friend function that is an overload and can be used in meta-programming. operator<< is a common example. Within a template you can stream your template parameter based on the overload existing. In this case it has to be a non-member but as it has to be declared in the header, it does not add extensibility, so I think static is preferable if it can be done. – CashCow Nov 15 '13 at 10:41
12

Static methods:

  • Provide encapsulation in the "namespace" created by the class. If your class is Animal and the static method is Create, you have to call it with Animal::Create. This is better than global functions, and allow implementing Factories and "virtual constructors" with relatively natural syntax.
  • Have access to static members. Such members are useful in some cases, and without static methods and members you would have to use global variables and functions.
Eli Bendersky
  • 231,995
  • 78
  • 333
  • 394
  • 1
    Also, if given an instance of the class, they have access to all private methods and functions too. This is very useful. – Macke Jan 18 '11 at 10:57
  • Static class members are also visible in free functions, and a friend free function can access non-public method. You're right about the first point, but it's only a matter of syntax, isn't it? Doesn't this contrast with the things said in the other question? – peoro Jan 18 '11 at 11:12
  • @peoro: (1) is mainly about the namespacing, not syntax. It's convenient to have a static method *inside* a class. Otherwise how do you relate to the user that it's part of the class logically? Once you have (1), static members are a much more convenient and "normal" way accessing static members than having global functions and declaring them friends inside the class, IMHO. – Eli Bendersky Jan 18 '11 at 12:11
  • regarding `1`, Sutter has been advocating the use of nonfriend nonmember functions for a while now, and this goes hand in hand with its definition that the public interface of a class is constituted of the class itself as well as all the free functions that are delivered within its header. – Matthieu M. Jan 18 '11 at 16:17
  • I actually prefer factories to static Create methods. You can make one base-class friend factory and other factories can derive from it. Although they do not get direct access to the class, the base-class friend factory does the actual creation, the derived classes gather the members together used to do it. – CashCow Nov 15 '13 at 10:44
  • A typical example of my last comment would be where you are streaming in the values from some or other source. Different implementations of the factory will use different formats, e.g. text stream, XML, database read, protocol buffers, boost serialize or whatever. Either way they gather the data members and call the friend factory class member to do the creation. – CashCow Nov 15 '13 at 10:47
4

Often, frankly, you shouldn't. Free functions are vastly under-rated.

The implicit "namespacing" you get from using a static member (pretending that the class is nothing more than a namespace for the static member, which is sort of true) is the only benefit that I can think of.

If the static function member needs persistent variables, the ability to have static data members along with it might also be useful.

Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989
3

Some people are wary of using static functions because it's often used by those who come from a procedural background and don't understand OO.

However there are many design patterns that make sense to be implemented using static member functions

For example. Singleton and Factory patterns to name a couple of the top my head, in fact most structural patterns that require object creation would require static member functions.

hhafez
  • 36,343
  • 33
  • 109
  • 143
  • 1
    yes, static functions are used for this purpose, but friend free functions should be able to do the same without any disadvantage... – peoro Jan 18 '11 at 11:14
  • But also beware of global data being disguised via a singleton. See the rich discussion on SO here: http://stackoverflow.com/questions/137975/… – rholmes just now edit – rholmes Jan 17 '14 at 02:33
1

There is no added value to static member functions, as you correctly identified. Worse, when used for implementation details this introduce extra dependencies (in term of compilation).

The only use that could not be emulated with an anonymous free-function, is the protected access, that is, a derived class accessing a parent static function. However, this is never required: you can just make it a regular member function instead (I assume you don't have global state, otherwise the static/friend distinction is not of immediate concern).

The use of static functions in template meta-programming has been evoked... however it is very similar to the inner types issue: it makes it difficult to provide a default version. On the other hand, a suitably defined free function (which takes the type as a pointer), can propose a template version:

struct some_traits
{
  static void doStuff();
};

// versus

struct some_traits {};

void doStuff(some_traits*);

// and the default: void doStuff(...);

And of course, there is always the question of why this should be a static function, when a member function would provide more flexibility to the user. To this effect I would cite the move the Standard Committee made with the Allocator concept: stateful allocators are now authorized, which gives us the opportunity of packing the nodes of a given map in a same page rather than spreading them all over the heap.

Finally, there is the interface issue. However it's been a long time already since Sutter advocated that a class and the free functions defined in the same header both constituted the public interface of this class => that is what ADL is for! So it is more something to comfort ancient OO-programmers than a "good practice".

Really, I don't see any benefit from using static member functions. I would like people would think the contrary to propose real cases.

Matthieu M.
  • 251,718
  • 39
  • 369
  • 642