Сначала я напишу пример, чтобы правильно решить вопрос.Хранилище данных с элементами статического шаблона
Прежде всего, я объявлю шаблон будет использоваться для создания одноплодного объекта (не автоматически создаются): singleton_base.h
template <class Derived>
class SingletonBase
{
public:
static Derived* instance() { assert(s_instance); return dynamic_cast<Derived*>(s_instance); }
protected:
SingletonBase() { assert(s_instance==0); s_instance=this; }
virtual ~SingletonBase() { assert(s_instance); s_instance=0; }
private:
static SingletonBase* s_instance;
};
template <class Derived>
SingletonBase<Derived>* SingletonBase<Derived>::s_instance = 0;
Теперь мы можем объявить любой класс, производные от шаблона , и каждый производный класс должен иметь свой собственный s_instance. Например:
child1.h
class Child1 : public SingletonBase<Child1>
{
...
void doSomething();
static void staticInvokeOne();
};
child2.h
class Child2 : public SingletonBase<Child2>
{
...
void doSomethingElse();
static void staticInvokeBoth();
};
У меня также есть реализация ребенка в child1.cpp и child2.cpp соответственно.
child1.cpp
void Child1::staticInvokeOne()
{
instance()->doSomething();
}
child2.cpp
void Child2::staticInvokeBoth()
{
Child1::instance()->doSomething();
instance()->doSomethingElse();
}
Теперь у меня есть Child1
и Child2
имеет свою собственную s_instance
и они указывают на единственный экземпляр этого класса в данный момент.
Вопрос о хранении этого статического члена данных s_instance
. В отличие от обычных статических элементов данных, я не указал, где он должен быть выделен. Я бы, конечно, хотел бы иметь SingletonBase<Child1>::s_instance
и SingletonBase<Child2>::s_instance
в child1.o и child2.o соответственно, но это то, что я могу ожидать или обеспечить соблюдение?
вопрос становится более сложным, если я ставлю Child1
и Child2
на две библиотеки - Lib1 и Lib2. Внутри Child2::staticInvokeBoth()
есть звонок Child1::instance()
. Насколько я понимаю, поведение gcc по умолчанию - генерировать копию SingletonBase<Child1>::s_instance
в каждом блоке компиляции, поэтому один экземпляр будет испускаться в lib2.
Будет ли также произведена копия SingletonBase<Child1>::s_instance
в lib2? Определенно, одна копия SingletonBase<Child1>::s_instance
должна быть в lib1. Если эти две библиотеки позже будут использоваться вместе в одном приложении, могу ли я быть уверенным, что существует только один экземпляр SingletonBase<Child1>::s_instance
и что оба его используют Child1::staticInvokeOne()
и Child2::staticInvokeBoth()
?
Насколько безопасно использовать этот подход со статикой, завернутой в шаблон, или есть какие-то недостатки?
Спасибо заранее!
Hm ... Это также относится к общим библиотекам? Будут ли эти имена разрешаться во время выполнения динамическим компоновщиком (предполагая linux)? Может ли он вводить в заблуждение DT_SYMBOLIC? – nyrl
Общие библиотеки могут быть сломаны, что плохо. Я был укушен проблемами с этим материалом перед разделяемыми библиотеками; обычно слабые символы разрешаются при конечном времени соединения и больше не могут быть объединены при динамическом времени связи. Stick со статическими библиотеками или вообще не использовать статические элементы в типах шаблонов. – bdonlan