Say I have a class Super
, in which I have a static member of type Super
, which just defines a commonly used instance of Super
// super.hpp
class Super
{
public:
Super(const double a):
m_a(a)
{}
double a() const { return m_a; }
static const Super thing; // use this a lot in code
private:
double m_a;
};
with implementation
// super.cpp
#include "super.hpp"
const Super Super::thing = Super(1.0); // definition
At this point I think everything is okay, but please correct me if not.
Now I also have subclasses of Super
, with similar static members
// sub.hpp
#include "super.hpp"
class Sub : public Super
{
public:
Sub(const double a):
Super(a)
{}
explicit Sub(const Super& obj):
Super(obj)
{}
static const Sub thing;
};
with implementation
// sub.hpp
#include "sub.hpp"
const Sub Sub::thing = Sub(Super::thing); // WORKS IN MYSTERIOUS WAYS
And finally an example usage
// main.cpp
#include <iostream>
#include "sub.hpp"
int main()
{
Super super = Super::thing;
std::cout << super.a() << std::endl;
Sub sub = Sub::thing;
std::cout << sub.a() << std::endl;
}
When I compile this with the following setup
// CMakeLists.txt
project (hello)
add_executable(hello main.cpp super.cpp sup.cpp)
I get the expected output
$ ./hello
1
1
but if I change the order of the cpp files in CMakeLists
(sub.cpp
before super.cpp
)
// CMakeLists.txt
project (hello)
add_executable(hello main.cpp sup.cpp super.cpp)
I get
$ ./hello
1
0
I think this is an example of static initialization order ‘fiasco’(?), and I have some understanding of why it happens.
So the question becomes: is there any way to get a warning about an un-initialized static, or any way to avoid the issue?
I've read How do I prevent the “static initialization order problem”?, but I was hoping to be able to keep the Sub::thing
interface, and avoid replacing it with Sub::thing()
.