What is the use of private static member functions?
I was looking at the request parser from the boost::asio example and I was wondering why the private member functions like is_char()
are static
? :
class request_parser
{
...
private:
static bool is_char(int c);
...
};
It is used in the function consume which is not a static function:
boost::tribool request_parser::consume(request& req, char input)
{
switch (state_)
{
case method_start:
if (!is_char(input) || is_ctl(input) || is_tspecial(input))
{
return false;
}
...
Only member functions can call is_char()
and no static member function is calling is_char()
. So is there a reason why these functions are static?
Solution 1:
This function could easily have been made freestanding, since it doesn't require an object of the class to operate within. Making a function a static member of a class rather than a free function gives two advantages:
- It gives the function access to private and protected members of any object of the class, if the object is static or is passed to the function;
- It associates the function with the class in a similar way to a namespace.
In this case it appears only the second point applies.
Solution 2:
So is there a reason why these functions are static?
Non-static
member functions have a hidden additional parameter called this
. Passing this doesn't come for free, so making a private
function static
can be seen as a means of optimization.
But it can also be seen as a means of expressing your requirements/design in your code: If that function doesn't need to refer to any member data of the class, why should it be a non-static
member function?
However, changing the type of any member function, public
or private
, static
or not, will require all clients to recompile. If this needs to be done for a private
function which those clients can never use, that's a waste of resources. Therefore, I usually move as many functions as possible from the class' private parts into an unnamed namespace in the implementation file.
Solution 3:
For this specific example, the choice for a static is_char()
is most likely a documentation one. The intent is to impress upon you that the is_char()
method is not contrained to a specific instance of the class, but the functionality is specific to the class itself.
In other words, by making it static
they are saying that is_char()
is a utility function of sorts...one which can be used irrespective of the state of a given instance. By making it private
, they are saying that you (as a client) should not try to use it. It either does not do what you think it does, or is implemented in a very constrained, controlled way.
@Mark Ransom's answer brings up a good point for the practical use of a private static member function. Specifically, that member function has access to private and protected members of either a static object or a passed instance of an instantiated object.
One common application of this is to abstract a pthread implementation in somewhat of an object oriented way. Your thread function must be static, but declaring it private limits the accessibility of that function to the class (to all but the most determined). The thread can be passed an instance of the class it's being "hidden" in, and now has access to perform logic using the object's member data.
Simplistic Example:
[MyWorkerClass.h]
...
public:
bool createThread();
private:
int getThisObjectsData();
pthread_t myThreadId_;
static void* myThread( void *arg );
...
[MyWorkerClass.cpp]
...
bool MyWorkerClass::createThread()
{
...
int result = pthread_create(myThreadId_,
NULL,
myThread),
this);
...
}
/*static*/ void* MyWorkerClass::myThread( void *arg )
{
MyWorkerClass* thisObj = (MyWorkerClass*)(arg);
int someData = thisObj->getThisObjectsData();
}
...