Search

8.12 — Static member functions

Static member functions

In the previous lesson on 8.11 -- Static member variables, you learned that static member variables are member variables that belong to the class rather than objects of the class. If the static member variables are public, we can access them directly using the class name and the scope resolution operator. But what if the static member variables are private? Consider the following example:

In this case, we can’t access Something::s_value directly from main(), because it is private. Normally we access private members through public member functions. While we could create a normal public member function to access s_value, we’d then need to instantiate an object of the class type to use the function! We can do better. It turns out that we can also make functions static.

Like static member variables, static member functions are not attached to any particular object. Here is the above example with a static member function accessor:

Because static member functions are not attached to a particular object, they can be called directly by using the class name and the scope resolution operator. Like static member variables, they can also be called through objects of the class type, though this is not recommended.

Static member functions have no *this pointer

Static member functions have two interesting quirks worth noting. First, because static member functions are not attached to an object, they have no this pointer! This makes sense when you think about it -- the this pointer always points to the object that the member function is working on. Static member functions do not work on an object, so the this pointer is not needed.

Second, static member functions can directly access other static members (variables or functions), but not non-static members. This is because non-static members must belong to a class object, and static member functions have no class object to work with!

Another example

Static member functions can also be defined outside of the class declaration. This works the same way as for normal member functions.

Here’s an example:

This program prints:

The next ID is: 1
The next ID is: 2
The next ID is: 3
The next ID is: 4
The next ID is: 5

Note that because all the data and functions in this class are static, we don’t need to instantiate an object of the class to make use of its functionality! This class utilizes a static member variable to hold the value of the next ID to be assigned, and provides a static member function to return that ID and increment it.

A word of warning about classes with all static members

Be careful when writing classes with all static members. Although such “pure static classes” (also called “monostates”) can be useful, they also come with some potential downsides.

First, because all static members are instantiated only once, there is no way to have multiple copies of a pure static class (without cloning the class and renaming it). For example, if you needed two independent IDGenerator objects, this would not be possible with a single pure static class.

Second, in the lesson on global variables, you learned that global variables are dangerous because any piece of code can change the value of the global variable and end up breaking another piece of seemingly unrelated code. The same holds true for pure static classes. Because all of the members belong to the class (instead of object of the class), and class declarations usually have global scope, a pure static class is essentially the equivalent of declaring functions and global variables in a globally accessible namespace, with all the requisite downsides that global variables have.

C++ does not support static constructors

If you can initialize normal member variables via a constructor, then by extension it makes sense that you should be able to initialize static member variables via a static constructor. And while some modern languages do support static constructors for precisely this purpose, C++ is unfortunately not one of them.

If your static variable can be directly initialized, no constructor is needed: you can initialize the static member variable at the point of definition (even if it is private). We do this in the IDGenerator example above. Here’s another example:

If initializing your static member variable requires executing code (e.g. a loop), there are many different, somewhat obtuse ways of doing this. One way that works with all variables, static or not, is to use a lambda and call it immediately.

The following code presents a method that behaves more like a regular constructor. However, it is a little tricky, and you’ll probably never need it, so feel free to skip the remainder of this section if you desire.

When static member s_initializer is defined, the init_static() default constructor will be called (because s_initializer is of type init_static). We can use this constructor to initialize any static member variables. The nice thing about this solution is that all of the initialization code is kept hidden inside the original class with the static member.

Summary

Static member functions can be used to work with static member variables in the class. An object of the class is not required to call them.

Classes can be created with all static member variables and static functions. However, such classes are essentially the equivalent of declaring functions and global variables in a globally accessible namespace, and should generally be avoided unless you have a particularly good reason to use them.


8.13 -- Friend functions and classes
Index
8.11 -- Static member variables

127 comments to 8.12 — Static member functions

  • init_static constructor

    // we'll use this static object to ensure the init_static constructor is called.

    // define our static initializer, which will call the init_static constructor, which will initialize s_mychars

    When we have a class Something and create an object from this class with a default constructor

    the constructor will be called to create the class. But why in the snippets above, the first command won't call the constructor of class init_static but the second command will!

    • nascardriver

      This is only a declaration, it doesn't create the object. The object gets created at its definition, which is

      `static` member variables can only be defined inside the class if they're declared `inline`. Otherwise they're just declarations and have to be defined outside.

  • Rushhahb

    I didn't get why you use 'return v' in the lambda?

    • nascardriver

      Here's what we're doing, but without the lambda

  • Static member functions have no *this pointer

    >>Static member functions have no *this pointer

    Then what would happen when we called a static member function using an object class? Is the address of the object passed to the static member function which has const 'this' pointer to that object as parameter ?

    • nascardriver

      The `this` pointer isn't passed anywhere in that case. The `static` member function is called as if you called it without an object.

  • CppLearner

    Hi Alex & Nascardriver,

    Thanks for your nice website! I'm learning a lot.

    Would you please let me ask you a question?
    Is there any reason that you didn't let the s_mychars be public?
    Is there any hidden intention over there?
    For my case, I just made a static function to get this from outside.

  • Remy

    I don't understand this part. I remember from previous chapters the syntax for lambda was [](){}. We can switch the parameter with the body?

    • nascardriver

      If a lambda doesn't have parameters, the parameter list can be omitted. Doing so introduces some restrictions, eg. the lambda can't have a trailing return type.
      The () at the end of the lambda are there to call it, the lambda ends at the closing curly brace.

      • Remy

        The way you're explaining it's like you can read my mind!

        There's levels to these stuff man I'm telling you~
        bruh~
        ~(applause)~

  • AJ

    The line before the summary section is still pointing to _init, instead it should be init_static

    "When static member s_initializer is defined, the _init() default constructor will be called (because s_initializer is of type _init) ..."

    Should be

    "When static member s_initializer is defined, the init_static() default constructor will be called (because s_initializer is of type init_static) ..."

  • Tablighi jamaat

    I think in the last code on line no 25 you meant

    and not

  • DV

    In the last example,

    should this be

    instead? Otherwise, I'm not sure where

    comes from.

  • Jan

    Hi,

    how would the last example change if MyClass was a template (not necessarily connected to the std::vector type)?

    • nascardriver

      Though, this blown up initialization is no longer required. You can use lambdas for complex initializations instead:

      We're creating a lambda and immediately calling it and initializing `s_mychars` with the return value. This works for all variables, not just static members. I'll update the lesson when I get around to it.

  • Samira Ferdi

    Hi, Alex and Nascardriver!

    The this pointer and static method caught my eyes!

    Alex said, "Static member functions don't have this pointer. Static member functions have two interesting quirks worth noting. First, because static member functions are not attached to an object, they have no this pointer! This makes sense when you think about it -- the this pointer always points to the object that the member function is working on. Static member functions do not work on an object, so the this pointer is not needed."

    But, we can use the static method throught the object of the class, right? So, does it mean that static method "can have" this pointer in this context?. Is there any explanation of this?

    • nascardriver

      A call to a static member function through an object isn't any different from calling the function via the class name. There is no `this` in static member functions.

  • Samira Ferdi

    Hi, Alex and Nascardriver!

    So, the whole point of static class members is using class functionalities without making any instances. Is this correct? Or are there other purposes?

    If it is, what is the point? Do static class members have uses in C++?

    • > Is this correct?
      Yes.

      > what is the point?
      A function is considered to be a part of a class, but it doesn't need an instance to work. If you want to use the function and don't have an instance, what do you do? Instantiation the class wastes resources. Even if you instantiated it, what do you initialize it to?

      > Do static class members have uses in C++?
      Yes, you'll see reasons to use `static` member functions later.

  • McDidda

    Hi,
    Consider the following snippet

    I'm not getting how line 8 and line 11 works (I was expecting compiler to throw error,as x is just member variable and it'll be attached with "enclose" object but still line 11 gets compiled in given snippet).

  • sekhar

    Hi Alex,

    Why does static variable defined inside a static function(here *inst of getInstance() function & val2 of printSample() static function) does not require it to be defined outside the class similar to any static variable declared as part of private/public section of a class(m_id  defined outside the class) ?

    • Alex

      In the above example, the "static int m_id" inside class Sample serves as a declaration, not a definition (as no memory is allocated until the class is instantiated). Because static member objects can be accessed even without an object, the definition needs to be somewhere. Thus, it's defined outside the class.

      In the case of inst, inst is a local static variable and is scoped to the function. Inst's declaration is also it's definition, so no separate definition is needed.

      • salah

        Hi Alex,
        Do you mean we have explicitly define static variable outside the class to allocate memory for them ?
        Unlike normal variables which will allocate memory when the object is instantiated ?

  • Ishak

    "First, because all static members are instantiated only once, there is no way to have multiple copies of a pure static class (without cloning the class and renaming it). For example, if you needed two independent IDGenerator objects, this would not be possible with a single pure static class."

    Isn't this the case with normal classes too? I can't have two IDGenerator objects, since all the objects share the same static members.

    "class declarations usually have global scope, a pure static class is essentially the equivalent of declaring functions and global variables in a globally accessible namespace, with all the requisite downsides that global variables have."

    Yeah but is it really as bad as global variables, even though I have static member functions that dictate how we can interact with the static variables ?

    thanks for the help

    • > Isn't this the case with normal classes too? I can't have two IDGenerator objects, since all the objects share the same static members.
      This is the case for every class with static members.

      > Yeah but is it really as bad as global variables
      No, they're nested in a class and access can be controlled via functions. I think Alex exaggerated in this sentence.

  • tinu

    Are MyClass::s_mychars and MyClass::s_initializer being defined twice in the last code example?

  • Gizmo

    I'm trying to implement a static function member using class headers and .cpp files, and I'm having trouble getting it to work.

    Here is a piece of example code demonstrating the issue.

    Example.h:

    Example.cpp:

    When I try to build the program, I get this error:
    "error: cannot declare member function 'static void Example::example()' to have static linkage [-fpermissive]"

    What am I doing wrong?

  • Nimbok

    In the section on static constructors (the lack thereof), is there a reason to use an inner class instead of a static function to initialize the vector? An initializer function could be called multiple times, inappropriately, but you can do the same with the inner class approach by instantiating another one (MyClass::_init ohno;). This would push another 'a', 'e', 'i', 'o', and 'u' onto the vector.

    • nascardriver

      Hi Nimbok!

      > is there a reason to use an inner class instead of a static function to initialize the vector?
      Using a class has the advantage that the constructor is automatically called when the object is created whereas we'd need to manually call a function.

      > An initializer function could be called multiple times
      The @_init class should be declared private, not public. If that was the case you wouldn't be able to create another @_init object outside of @MyClass.
      Alternatively (but less efficient) one could check @s_mychars.empty() to see if the vector has already been filled.

  • Guozili

    Hi Alex,
    When you talk about warnings about classes with all static members, you mentioned that "First, because all static members are instantiated only once, there is no way to have multiple copies of a pure static class (without cloning the class and renaming it). For example, if you needed two independent IDGenerator objects, this would not be possible with a single pure static class."
    But I still could not understand it, if I define:

    Something wrong?

    • nascardriver

      Hi Guozili!

      The problem here is that A and B are equivalent. Take the following code for example

      Expected output

      Actual output

      You cannot have two different IDGenerators with all static members.

  • Mr. Nobody

    Thanks alot...
    XXX

  • Luhan

    At the end of tutorial you show how to initialize a static vector through iteration, i didn't understand this:

    is this  _init  a class, and you create this member so when you define it at the same time the constructor is called and executes the push inside the vector?

  • Cunni

    Hi Alex,
    In the paragraph of the A word of warning about classes with all static members section, you wrote:

    "(...)Because all of the members belong to the class (instead of object of the class), and class declarations usually have global scope, a pure static class is essentially the equivalent of declaring functions and global variables in a globally accessible namespace, with all the requisite downsides that global variables have."

    This only applies to static members that are within the public accessors, correct? If the static members are made private, than they are no longer in the global namespace?

    • Alex

      Well, the class members aren't in the global namespace either way (they're in the class namespace, which is in the global namespace) -- but the end result is similar, the members are accessible by everybody from everywhere.

      If you make those members private, then they can no longer be accessed from outside the class, which helps alleviate the issue.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]