«Не вызывать виртуальные методы из конструкторов». Это только иногда PITA, но только потому, что в C # я не могу решить, в какой точке конструктора вызывать конструктор моего базового класса. Почему бы и нет? Инфраструктура .NET позволяет это, так что есть веская причина для C #, чтобы не позволять это?
Черт!
Вы правы, что подобная статическая инициализация не является поточно-ориентированной ( здесь - это статья, в которой обсуждается, во что компилятор ее превратит)
На данный момент, не существует стандартного, поточно-безопасного, переносимого способа инициализации статических синглтонов. Можно использовать блокировку с двойной проверкой, но вам понадобятся потенциально непереносимые библиотеки потоков (см. Обсуждение здесь ).
Вот несколько вариантов, если безопасность потоков является обязательной:
Пример для 1:
// in a cpp:
namespace {
Dog dog("Lassie");
}
Dog* MyClass::BadMethod()
{
return &dog;
}
Пример для 4:
Dog* MyClass::BadMethod()
{
static scoped_ptr<Dog> pdog;
{
Lock l(Mutex);
if(!pdog.get())
pdog.reset(new Dog("Lassie"));
}
return pdog.get();
}
Не уверен, что вы имеете в виду или нет, но вы можете удалить зависимость ускорения в системах POSIX, вызвав вместо этого pthread_once
. Я полагаю, вам нужно было бы сделать что-то другое в Windows, но избегать этого, в первую очередь, у boost есть библиотека потоков, и почему люди платят цену, зависящую от нее.
Выполнение чего-либо «поточно-безопасно» неотъемлемо связан с реализацией ваших потоков. Вы должны зависеть от чего-то , даже если это только платформо-зависимая модель памяти. В чистом C ++ 03 просто невозможно предположить что-либо о потоках, которые выходят за рамки языка.
Один из способов сделать это, не требующий мьютекса для обеспечения безопасности потоков, - это сделать синглтон статическим файлом, а не статической функцией:
static Dog dog("Lassie");
Dog* MyClass::BadMethod()
{
return &dog;
}
The Dog
экземпляр будет инициализирован перед запуском основного потока. Статические переменные файла имеют известную проблему с порядком инициализации, но пока Dog не полагается на какие-либо другие статические параметры, определенные в другой единице трансляции, это не должно вызывать беспокойства.
Комментарий Мартина Коничека, чтобы полностью отключить выбор элементов самым простым способом:
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="false"/>
</Style>
</ListView.ItemContainerStyle>
...
</ListView>
Однако, если вам по-прежнему требуются функциональные возможности ListView, например возможность выбора элемента, вы можете визуально отключить стиль выбранного элемента следующим образом:
Вы можете сделать это несколькими способами, от изменения ListViewItem ControlTemplate , чтобы просто установить стиль (намного проще). Затем вы создаете MyInit ()
для создания и уничтожения одного объекта каждого типа, который содержит одну из этих статик.
Единственная альтернатива - наложить еще одно ограничение на то, как они могут использовать ваш сгенерированный код (используйте Boost, потоки Win32 и т. Д.). На мой взгляд, любое из этих решений приемлемо - можно создавать правила, которым они должны следовать.
Если они не следуют правилам, изложенным в вашей документации, то все ставки отменены. Правило, согласно которому они должны вызывать функцию инициализации или зависеть от Boost, для меня не является необоснованным.
Можно создавать правила, которым они должны следовать.Если они не соблюдают правила, изложенные в вашей документации, то все ставки отключены. Правило, согласно которому они должны вызывать функцию инициализации или зависеть от Boost, для меня не является необоснованным.
Можно создавать правила, которым они должны следовать.Если они не соблюдают правила, изложенные в вашей документации, то все ставки отключены. Правило, согласно которому они должны вызывать функцию инициализации или зависеть от Boost, для меня не является необоснованным.
AFAIK, единственный раз, когда это было сделано безопасно и без мьютексов или предварительной инициализации глобальных экземпляров, было в Мэтью Уилсон Imperfect C ++ , в котором обсуждается, как это сделать с помощью «спинового мьютекса». Я не приблизился к своей копии, поэтому сейчас не могу сказать вам более точно.
IIRC, есть несколько примеров использования этого внутри библиотек STLSoft , хотя Я не могу вспомнить, какие компоненты сейчас.