|
Вариации Перед тем как описывать сами алгоритмы уплотнения, давайте рассмотрим другие варианты исходной постановки задачи. Они не оказывают принципиального влияния на архитектуру или алгоритмы, а только на идиомы С++ в их реализации. Невидимые ведущие указатели Чтобы не использовать шаблоны дескрипторов и ведущих указателей, можно было организовать множественное наследование ведущих указателей от VoidPtr и гомоморфного базового класса. Иначе говоря, ведущие указатели становятся невидимыми, как объяснялось в предыдущих главах. В игру вступают все механизмы, сопутствующие идиоме невидимых указателей (например, производящие функции). class Foo { public: static Foo* make(); // Возвращает пару указатель-указываемый объект virtual void Member1() = 0; // И т.д. для открытого интерфейса }; // В файле foo.cpp class FooPtr : public Foo, public VoidPtr { public: FooPtr(Foo* foo, size_t size) : VoidPtr(foo, size) {} virtual ~FooPtr() { delete (Foo*)address; } virtual void Member1() { ((Foo*)address)->Member1(); } // И т.д. для остальных открытых функций }; class RealFoo : public Foo { ... }; Foo* Foo::make() { return new FooPtr(new RealFoo, sizeof(RealFoo)); } // В клиентском коде class Bar { private: Foo* foo; // На самом деле невидимый указатель public: Bar() : foo(Foo::make()) {} }; Такое решение улучшает инкапсуляцию применения ведущих указателей. Кроме того, оно позволяет производящим функциям решить, какие экземпляры должны управляться подобным образом, а какие - с помощью обычных невидимых указателей или даже вообще без указателей. Все прекрасно работает, пока вы соблюдаете осторожность и выделяете в VoidPtrPool достаточно места для FooPtr. Помните, что из-за множественного наследования по сравнению с VoidPtr размер увеличивается, по крайней мере, на v-таблицу. Объекты классов Возможен и другой вариант - потребовать, чтобы все объекты происходили от общего класса-предка, способного возвратить объект класса для данного объекта или, по крайней мере, размер объекта. В этом случае вам уже не придется хранить в указателе объект экземпляра, поскольку его можно будет получить у объекта класса. Если вы готовы смириться с некоторым насилием в отношении типов в дескрипторах, это также позволит вам избежать шаблонов второго уровня, используемых для главных указателей. Вместо void* в VoidPtr можно будет хранить CommonBase* (где CommonBase - общий базовый класс). Мы избавляемся от переменной size, от необходимости иметь шаблон, производный от VoidPtr, и от виртуального деструктора в VoidPtr, и как следствие - от 4-байтового адреса v-таблицы. С другой стороны, если управляемые объекты уже содержат v-таблицы и не принуждают вас к применению множественного наследования, дополнительных затрат не будет. |
Copyright 2005. Климов Александр. All Right Reserved.