На самом деле, с помощью Singletons вы можете довольно эффективно контролировать порядок инициализации глобальных / статических объектов в C ++.
Например, скажем, у вас есть:
class Abc
{
public:
void foo();
};
и соответствующий объект, определенный в глобальной области видимости:
Abc abc;
Тогда у вас есть класс:
class Def
{
public:
Def()
{
abc.foo();
}
};
, который также имеет объект, определенный в глобальной области видимости:
Def def;
В этой ситуации у вас нет контроля над порядком инициализации, и если сначала инициализируется def, то, скорее всего, ваша программа вылетит, потому что она вызывает метод foo () в Abc, который еще не был инициализирован.
Решение состоит в том, чтобы функция в глобальном масштабе выполняла что-то вроде этого:
Abc& abc()
{
static Abc a;
return a;
}
и тогда Def будет выглядеть примерно так:
class Def
{
public:
Def()
{
abc().foo();
}
};
Таким образом, abc всегда гарантированно инициализируется перед использованием, поскольку это произойдет во время первого вызова функции abc (). Аналогично, вы должны сделать то же самое с глобальным объектом Def, чтобы у него не было неожиданных зависимостей инициализации.
Def& def()
{
static Def d;
return d;
}
Если вам необходимо строго контролировать порядок инициализации в дополнение к простой проверке того, что все инициализировано перед его использованием, поместите все глобальные объекты в глобальный синглтон следующим образом.
struct Global
{
Abc abc;
Def def;
};
Global& global()
{
static Global g;
return g;
}
И сделать ссылки на эти предметы следующим образом:
//..some code
global().abc.foo();
//..more code here
global().def.bar();
Независимо от того, кто получает вызов первым, правила инициализации члена C ++ гарантируют, что объекты abc и def инициализируются в порядке, который они определены в классе Global.