#include <memory>
#include <oess_1/defs/h/ex.hpp>
#include <oess_1/stdsn/h/declspec.hpp>
#include <oess_1/stdsn/h/serializable.hpp>
#include <oess_1/stdsn/h/errno.hpp>
Пространства имен | |
namespace | oess_1 |
namespace | oess_1::stdsn |
Классы | |
class | refcountable_policy_t |
Политика владения указателем на основе подсчета ссылок. Подробнее... | |
class | cloneable_policy_t |
Класс политики умного указателя, основанной на клонировании объектов при копировании. Подробнее... | |
struct | shptr_type_tag |
Тег, который должен показывать, к какому типу нужно делать кастинг в классе умного указателя. Подробнее... | |
class | shptr_skeleton_t |
Каркас для реализации функциональности умных указателей. Подробнее... | |
class | shptr_t |
Класс умного указателя на сериализуемый объект. Подробнее... | |
Макросы | |
#define | _OESS_1__STDSN__SHPTR_HPP_ |
#define | OESS_1_SHPTR_IFACE(shptr_type, referred_type, base_type) |
Макрос для упрощения настройки умных указателей. |
#define OESS_1_SHPTR_IFACE | ( | shptr_type, | |||
referred_type, | |||||
base_type | ) |
Макроопределение:
private : \ typedef base_type base_type_typedef__; \ typedef base_type base_type_t; \ public : \ shptr_type() {} \ shptr_type( referred_type * p ) : base_type_typedef__( p ) {} \ shptr_type( const shptr_type & o ) : base_type_typedef__( o ) {} \ virtual ~shptr_type() {} \ shptr_type & \ operator=( const shptr_type & o ) \ { base_type_typedef__::operator=( o ); return *this; } \ referred_type * \ get() { return cast_to( oess_1::stdsn::shptr_type_tag< referred_type >() ); } \ const referred_type * \ get() const { return cast_to( oess_1::stdsn::shptr_type_tag< referred_type >() ); } \ referred_type * \ operator->() { return get(); } \ const referred_type * \ operator->() const { return get(); } \ referred_type & \ operator*() { return *get(); } \ const referred_type & \ operator*() const { return *get(); } \ private :
Класс oess_1::stdsn::shptr_t не предоставляет операторов разыменования указателей. Поэтому, его использование не так удобно, как, например, класса std::auto_ptr. Предполагается, что если требуется класс, аналогичный std::auto_ptr для конкретного сериализуемого класса, то такой класс будет реализован программистом. И в этом классе программист сам реализует все необходимые ему средства:
// Какой-то сериализуемый класс. class some_class_t : public oess_1::stdsn::serializable_t { ... }; // Умный указатель, настроенный для some_class_t. class some_class_ptr_t : public oess_1::stdsn::shptr_t { OESS_SERIALIZER( some_class_ptr_t ) public : some_class_ptr_t(); some_class_ptr_t( some_class_t * p ); some_class_ptr_t( const some_class_ptr_t & o ); virtual ~some_class_ptr_t(); some_class_ptr_t & operator=( const some_class_ptr_t & o ); some_class_t * get(); const some_class_t * get() const; some_class_t * operator->() { return get(); } const some_class_t * operator->() const { return get(); } some_class_t & operator*() { return *get(); } const some_class_t & operator*() const { return *get(); } };
В большинстве случаев содержимое всех конкретных классов умных указателей будет одинаковым. Поэтому, для облегчения написания подобных классов предназначен макрос OESS_1_SHPTR_IFACE. С его помощью описанный выше some_class_ptr_t можно было написать так:
// Какой-то сериализуемый класс. class some_class_t : public oess_1::stdsn::serializable_t { ... }; // Умный указатель, настроенный для some_class_t. class some_class_ptr_t : public oess_1::stdsn::shptr_t { OESS_SERIALIZER( some_class_ptr_t ) OESS_1_SHPTR_IFACE( some_class_ptr_t, some_class_t, oess_1::stdsn::shptr_t ) };
{type some_class_ptr_t {super oess_1::stdsn::shptr_t} }
class __declspec(dllexport) some_class_ptr_t : public oess_1::stdsn::shptr_t { ... };
shptr_type | Имя типа, в котором использован макрос (т.е. имя типа умного указателя). Это имя необходимо для описания конструкторов и деструктора. Поэтому это должно быть короткое (не полностью квалифицированное) имя -- например some_class_ptr_t, а не my_namespace::some_class_ptr_t. | |
referred_type | Имя типа, на который указывает умный указатель. Должен быть полностью квалифицированным именем типа (т.к. это имя передается в метод oess_1::stdsn::shptr_t::cast_to(), то оно должно быть точно таким, каким указано в DDL). | |
base_type | Имя типа, от которого произведен данный класс умного указателя. Может быть полностью квалифицированным именем типа. |
// Базовый тип... class my_base_t : public oess_1::stdsn::serializable_t { ... }; // ... и умный указатель для него. class my_base_ptr_t : public oess_1::stdsn::shptr_t { OESS_SERIALIZER( my_base_ptr_t ) OESS_1_SHPTR_IFACE( my_base_ptr_t, my_base_t, oess_1::stdsn::shptr_t ) }; // Производный класс... class my_derived_t : public my_base_t { ... }; // ... и умный указатель для него. class my_derived_ptr_t : public my_base_ptr_t { OESS_SERIALIZER( my_derived_ptr_t ) OESS_1_SHPTR_IFACE( my_derived_ptr_t, my_derived_t, my_base_ptr_t ) };
Благодоря этому ссылку на объект my_derived_ptr_t можно передать как ссылку на объект my_base_ptr_t:
void f( const my_base_ptr_t & ref ) { ... } void g() { my_derived_ptr_t ptr( new my_derived_t() ); f( ptr ); }
Макрос OESS_1_SHPTR_IFACE(shptr_type, referred_type, base_type) раскрывается следующим образом:
private : typedef base_type base_type_t; public : // Конструкторы и деструктор. shptr_type() {} shptr_type( referred_type * p ) : base_type_t( p ) {} shptr_type( const shptr_type & o ) : base_type_t( o ) {} virtual ~shptr_type() {} // Оператор копирования. shptr_type & operator=( const shptr_type & o ) { base_type_t::operator=( o ); return *this; } // Функции получения указателя, приведенного к нужному типу. referred_type * get() { return cast_to( shptr_type_tag< referred_type >() ); } const referred_type * get() const { return cast_to( shptr_type_tag< referred_type > ); } referred_type * operator->() { return get(); } const referred_type * operator->() const { return get(); } referred_type & operator*() { return *get(); } const referred_type & operator*() const { return *get(); } private :