|
Программирование >> Перегруженные имена функций и идентификаторы
private: A* pa; public: PA(A* p){pa = p; p->addref();} ~PA(){pa->release();} A* operator ->(){return pa;} Что мы видим? Есть класс PA, который умеет принимать нормальный указатель на объект класса A и выдавать его же по обращению к селектору членов класса. Ну и что? - скажете вы, - Как это может помочь? . За помощью обратимся к двум примерам, которые иллюстрирует эффективность использования класса PA: A* pa = new A(); pa->addref(); pa->do something(); pa->release(); PA pa = new A(); pa->do something(); Посмотрим внимательнее на эти два отрывка... Что видим? Видим экономию двух строчек кода. Здесь вы наверное скажете: И что, ради этого мы столько старались? . Но это не так, потому что с введением класса PA мы переложили на него все неприятности со своевременными вызовами addref и release для класса A. Вот это уже что-то стоит! Дальше больше, можно добавить всякие нужные штучки, типа оператора присваивания, еще одного селектора (или как его некоторые называют разименователь указателя) и так далее. Таким образом получится удобная вещь (конечно, если все это дело завернуть в шаблон. Теперь немного сменим направление рассуждений. Оказывается существуют такие вещи, как Мудрые указатели , Ведущие указатели , Гениальные указатели , Грани , Кристаллы - в общем, хватает всякого добра. Правда, в практичности этих поделок можно усомниться, несмотря на их изящество . То есть, конечно, они полезны, но не являются, своего рода, панацеей (кроме ведущих указателей). В общем особую роль играют только ведущие и умные указатели. Начнем с такого класса как Countable, который будет отвечать за подсчет чего либо. Итак он выглядит примерно так (в дальнейшем будем опускать реализации многих функций из-за их тривиальности, оставляя, тем самым, только их объявления: class Countable private: int count; public: int increment (); int decrement (); Здесь особо нечего говорить, кроме того, что, как всегда, этот класс можно сделать более удобным , добавив такие вещи, как поддержку режима многопоточности и т.д. Следующий простой класс прямо вытекает из многопоточности и осуществляет поддержку этого режима для своих детей: class Lockable public: void lock(); void unlock(); bool islocked(); Этот класс не вносит никакой новизны, но стандартизует поддержку многопоточности при использовании, например, различных платформ. Теперь займемся собственно указателями: class AutoDestroyable : public Countable public: virtual int addref (); virtual int release (); protected: virtual ~AutoDestroyable(); Из кода видно, что этот класс занимается подсчетом ссылок и убивает себя если пришло время . А сейчас процитируем код умного указателя, для того чтобы синхронизовать наши с вами понимание этого чуда. template <class T> class SP private: T* m pObject; public: SP ( T* pObject){ m pObject = pObject; } ~SP () { if( m pObject ) m pObject->release (); } T* operator -> (); T& operator * (); operator T* (); Это уже шаблон, он зависит от объекта класса, к которому применяется. Задача умного указателя была рассмотрена выше и итог при сравнении с ситуацией без его использования положителен только тем, что для объекта, создаваемого в куче, не надо вызывать оператор delete - он сам вызовется, когда это понадобится. Теперь остановимся на минутку и подумаем, когда мы можем использовать этот тип указателей, а когда нет. Главное требование со стороны SP, это умение основного объекта вести подсчет ссылок на себя и уничтожать себя в тот момент, когда он не становится нужен. Это серьезное ограничение, поскольку не во все используемые классы вы сможете добавить эти
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |