Программирование >>  Перегруженные имена функций и идентификаторы 

1 ... 122 123 124 [ 125 ] 126 127 128 ... 210


возможности. Вот несколько причин, по которым вы не хотели бы этого (или не можете):

Вы используете закрытую библиотеку (уже скомпилированную) и физически не можете добавить кусок кода в нее.

Вы используете открытую библиотеку (с исходными кодами), но не хотите изменять ее как-либо, потому что все время меняете ее на более свежую (кто-то ее делает и продвигает за вас).

И, наконец, вы используете написанный вами класс, но не хотите по каким-либо причинам вставлять поддержку механизма подсчета ссылок.

Итак, причин много или по крайней мере достаточно для того, чтобы задуматься над более универсальным исполнением SP. Посмотрим на схематичный код ведущих указателей и дескрипторов :

template <class T>

clacc MP : public AutoDestroyable

private:

T* m pObj; public:

MP(T* p);

T* operator ->(); protected:

operator T*();

template <class T>

class H

private:

MP<T>* m pMP; public:

H(T*);

MP& operator T->(); bool operator ==(H<T>&); H operator =(H<T>&);



Что мы видим на этот раз? А вот что. MP - это ведущий указатель, т.е. такой класс, который держит в себе объект основного класса и не дает его наружу. Появляется только вместе с ним и умирает аналогично. Его главная цель, это реализовывать механизм подсчета ссылок.

В свою очередь H - это класс очень похожий на SP, но общается не с объектом основного класса, а с соответствующим ему MP.

Результат этого шаманства очевиден - мы можем использовать механизм умных указателей для классов не добавляя лишнего кода в их реализацию.

И это действительно так, ведь широта использования такого подхода резко увеличивается и уже попахивает панацеей.

Что же можно сказать о многопоточности и множественном наследовании: при использовании классов MP и H - нет поддержки этих двух вещей. И если с первой все понятно (нужно наследовать MP от Lockable), то со вторым сложнее.

Итак, посвятим немного времени описанию еще одного типа указателей, которые призваны решить проблему множественного наследования (а точнее полиморфизма).

Рассмотрим классы PP и TP:

class PP : public AutoDestroyable

template<class T> class TP

protected: T* m pObject; PP* m pCounter;

public:

TP ();

TP ( T* pObject );

TP<T>& operator = ( TP<T>& tp );

T* operator -> ();

T& operator * ();

operator T* ();



bool operator == ( TP<T>& tp );

Класс PP является фиктивным ребенком AutoDestroyable и

вы не забивайте себе этим голову. А вот класс TP можно посмотреть и попристальнее.

Схема связей в этом случае выглядит уже не H->MP->Obj, а PP<-TP->Obj, т.е. Счетчик сс1лок (а в данном случае, это PP) никак не связан с основным объектом ии каким-либо другим и занимается только своим делом - ссылками. Таким образом, на класс TP ложится двойная обязанность: выглядеть как обычный указатель и отслеживать вспомогательные моменты, которые связаны со ссылками на объект.

Как же нам теперь использовать полиморфизм? Ведь мы хотели сделать что-то вроде:

class A : public B

TP<A> a; TP<B> b;

a = new B;

b = (B*)a;

Для этого реализуем следующую функцию (и внесем небольшие изменения в класс TP для ее поддержки):

template <class T, class TT> TP<T> smart cast ( TP<TT>& tpin ); Итак, теперь можно написать что-то вроде (и даже будет работать):

class A : public B

TP<A> a; TP<B> b; a = new B;

b = smart cast<B, A>(a);

или если вы используете Visual C++, то даже b = smart cast<B>(a);



1 ... 122 123 124 [ 125 ] 126 127 128 ... 210

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика