Can someone give me an example about when that might come in handy?I can't figure anything! Why would one want a static member function? What problem could you solve just with that?
Are static member functions ever used?
If you need to pass a regular C-compatible function pointer to something (like a Windows Procedure, or a thread procedure) it has to be static so the calling conventions are the same.
Also if you have a member function that doesn't access any members of the class (except static ones) it should be static as well.
Class factories use static Create methods which act a bit like constructors as well (they create a new object and return the address).
Evil singletons use static methods to get the instance as well...
Named constructor idiom, as one example.
class Shape
{
Shape(); //Default constructor.
Shape(VertexArray vertices); //Create a shape from a list of points.
static Shape CreateRectangle(x, y, width, height); //Convenience function to create and return a shape.
};
Shape shape(......);
Shape myRectangle = Shape::CreateRectangle(x, y, width, height);
In my own code-base oftentimes I have static member variables that are shared by every instance of that class (for example, "DefaultTileImage" of a Tile class).
Due to API requirements, I can't load images until after the API has been initialized and a window created, so I can't initialize and load DefaultTileImage in the source file:
Image Tile::DefaultTileImage = NULL; //I can't load it here, because of the API requirements.
So instead, I have a static function to load the Tile's static DefaultTileImage, after the API has been initialized.
...API is initialized...
...game is being initialized...
Tile::LoadDefaultTileImage("image");
Another case which I was just reviewing is differentiation of action. Take for example the normalize function in a vector3 class:
class vector3
{
public:
void Normalize(); // Normalize "this" vector without return. Folks will be annoyed..
// or
vector3 Normalize() const; // Normalize the vector and return it, not modifying "this".
// or a poorly written library could have the above and this next one at the same time:
vector3& Normalize(); // Normalize "this" vector and return a reference.
// Ack, same usage completely different meaning, which gets called? Probably the compiler would bitch
// since it doesn't know which to call in some cases.
};
So with a static function you could get both behaviors in an explicit manner:
class vector3
{
public:
vector3& Normalize(); // Normalize "this" vector.
static vector3 Normalize( const vector3& );
};
There is the static factory pattern. And my math library (and some utilities) are made out of static methods too.
A cross product isn't something inherent of an object. So my static math class deals with that (and a whole other bunch of operations).
Excellent example!Another case which I was just reviewing is differentiation of action.
Some people try to distinguish them by their names as well. 'Normalize' (normalizes 'this'), 'Normalized' (returns a copy that is normalized). The benefit is that you see the difference when reading the function when in use, and not just when reading the function definition.So with a static function you could get both behaviors in an explicit manner:
class vector3 { public: vector3& Normalize(); // Normalize "this" vector. static vector3 Normalize( const vector3& ); };
From the signatures there is pretty much no way you can read those incorrectly or expect the behavior to be different than it is. Not suggesting this is a great answer for a vector, I was just thinking about this recently as mentioned and this was a use/case.
vecA.Normalize(); //Unknown whether this is returning or not.
vs:
Vector vecB = vecA.Normalized(); //Definitely returning.
Typically I just have my codebase always operate on 'this' and copy explicitely, but that's just by habit - not by consciously thinking it through - but I figure I'd throw out the naming difference as an idea that others sometimes use. I started a thread inquiring about this a year ago, which might be interesting.Also note that with static vs non-static similarly named functions, you have to be aware of an unintuitive C++ feature: You can call static functions from a class instance.
myInstance.StaticFunction(27, "blah");
I always call my static functions using the class scope explicitly (even if called from within other class functions), as there is zero ambiguity in that method:int result = MyClass::StaticFunction(27, "blah");
I generally use them for user callbacks:
class IWindow
{
public:
//pass in ptr to object as we no longer have access to it directly
static int OnMouse(int, int, int, IWindow*);
};
IWindow* w = new IWindow;
w->OnMouse = MyMouseProc;
If you want to implement sort of an auto increment type id (here called family):
#pragma once
struct BaseComponent
{
typedef unsigned int Family;
protected:
static Family family_count;
};
template <typename Derived>
struct Component : public BaseComponent {
static Family family(void);
};
template<typename C>
unsigned int Component<C>::family(void) {
static BaseComponent::Family Family = family_count++;
return Family;
}
//"always" = if first called in that order
class Derived : public Component<Derived> {};
Derived::family(); // always 0
class Derived2 : public Component<Derived2> {};
Derived2::family(); //always 1
I generally use them for user callbacks:
class IWindow { public: //pass in ptr to object as we no longer have access to it directly static int OnMouse(int, int, int, IWindow*); }; IWindow* w = new IWindow; w->OnMouse = MyMouseProc;
That's not going to compile... you'd need to declare the functions pointer as
static int (*OnMouse)(int, int, int, IWindow*);
and you can use pointer to member functions for that anyway
If you want to implement sort of an auto increment type id (here called family):
#pragma once struct BaseComponent { typedef unsigned int Family; protected: static Family family_count; }; template <typename Derived> struct Component : public BaseComponent { static Family family(void); }; template<typename C> unsigned int Component<C>::family(void) { static BaseComponent::Family Family = family_count++; return Family; } //"always" = if first called in that order class Derived : public Component<Derived> {}; Derived::family(); // always 0 class Derived2 : public Component<Derived2> {}; Derived2::family(); //always 1
And I'm not sure that will compile either since you can't call a function outside of a function body unless it is as an initializer for a global or static object... unless that's new in C++11