Если у меня есть две статические переменные в разных единицах компиляции, то их порядок инициализации не определен. Этот урок хорошо изучен.C++ Инициализация статических переменных (еще раз)
Вопрос, который у меня есть: все статические переменные уже выделены, когда первый инициализируется. Другими словами:
static A global_a; // in compilation unit 1
static B global_b; // in compilation unit 2
struct A {
A() { b_ptr = &global_b; }
B *b_ptr;
void f() { b_ptr->do_something(); }
}
int main() {
global_a.f();
}
Будет b_ptr пункт действительной части памяти, где выделяется и инициализируется B во время выполнения основной функции? На всех платформах?
Longer история:
Компиляция блок 1 является Qt библиотеки. Другой - мое приложение. У меня есть пары классов, основанных на QObject, что мне нужно создать экземпляр с помощью строки имени класса. Для этого я придумал шаблонный класс фабрики:
class AbstractFactory {
public:
virtual QObject *create() = 0;
static QMap<const QMetaObject *, AbstractFactory *> m_Map;
}
QMap<const QMetaObject *, AbstractFactory *> AbstractFactory::m_Map; //in .cpp
template <class T>
class ConcreteFactory: public AbstractFactory {
public:
ConcreteFactory() { AbstractFactory::m_Map[&T::staticMetaObject] = this; }
QObject *create() { return new T(); }
}
#define FACTORY(TYPE) static ConcreteFactory <TYPE> m_Factory;
Затем я добавить этот макрос на каждом QObject определении подкласса:
class Subclass : public QObject {
Q_OBJECT;
FACTORY(Subclass);
}
Наконец я могу создать экземпляр класса по имени типа:
QObject *create(const QString &type) {
foreach (const QMetaObect *meta, AbstractFactory::m_Map.keys() {
if (meta->className() == type) {
return AbstractFactory::m_Map[meta]->create();
}
}
return 0;
}
Таким образом, класс получает статический экземпляр QMetaObject
: Subclass::staticMetaObject
из библиотеки Qt - он автогенерируется в Q_OBJECT
макросов. Я думаю. А затем макрос FACTORY
создает статический экземпляр ConcreteFactory<Subclass>
. ConcreteFactory в своем конструкторе пытается ссылаться на подкласс :: staticMetaObject.
И я был очень доволен этой реализацией на linux (gcc), пока не скомпилировал его с Visual Studio 2008. По какой-то причине AbstractFactory :: m_Map был пуст во время выполнения, и отладчик не сломался на заводском конструкторе ,
Так вот откуда исходит запах статических варов, ссылающихся на другие статические вары.
Как я могу оптимизировать этот код, чтобы избежать всех этих ловушек?
Ну, этот код сильно отличается от вашего оригинального вопроса ... в вашем исходном вопросе вы сохранили адрес глобальной переменной, но не получили доступ к нему до `main`, и к этому времени глобальный был полностью построен. Но теперь вы пытаетесь использовать его изнутри конструктора глобального объекта ConcreteFactory, который намного раньше, чем `main`. – 2010-12-07 18:21:30
В подробном примере я сохраняю адрес статической переменной `staticMetaObject`. Но он доступен из `main` через функцию` create` во время выполнения - точно так, как я описал в упрощенном примере.Меня не интересует `static QMap <...> m_Map` - в моем реальном коде фактически завернута в статическую функцию, как это предлагал @Martin York. Таким образом, подробный пример касается ссылки на `staticMetaObject` из конструктора ConcreteFactory. – 2010-12-07 19:18:49