Search code examples
c++initializationstatic-variables

Is parent's static variables guaranteed to be initialized before child's static variables?


I have a C++ code looks like this

Parent.hpp

class Parent {
    static std::map<std::string, std::function<void()>> list;
}

Parent.cpp

#include "Parent.hpp"
std::map<std::string, std::function<void()>> Parent::list;

Child.hpp

#include "Parent.hpp"
class Child : Parent {
    static bool isRegistered = registerComponent();
    std::function<void(GameObject* go, void* arr)> add;
    static bool registerComponent();

Child.cpp

#include "Child.hpp"
    static bool Child::isRegistered = registerComponent();
    std::function<void(GameObject* go, void* arr)> Child::add = []() {
        //do something
    }
    static bool Child::registerComponent() {
        if (add) {
            list["child"] = Child::add;
            return true;
        }
        else return false
    }

is list guaranteed to be initialized before I call registerComponent()? I have read this post When are static C++ class members initialized? I think it's not guaranteed, but I am not 100% sure.


Solution

  • No it's not. The way you wrote it, there is no order of initialization guarantee between list and the static members of Child.

    What is guaranteed is that static data is initialized prior to any use (according to the one definition rule, that is) of any function in their translation unit. So if you were to make registerComponent a member of Parent, everything will be alright between the Parent class and its children.

    class Parent {
        static std::map<std::string, std::function<void()>> list;
      protected:
        // Implemented in the same TU where list is defined
        static bool registerComponent(std::string k, std::function<void()> v);
    };
    

    Now any child class calling registerComponent will be using a function from the translation unit that defined list, so list will definitely be initialized before the function is executed.