|
Программирование >> Перегруженные имена функций и идентификаторы
Free (); T * operator->() { return p; } T const * operator->() const { return p; } operator T const * () const { return p; } T const & GetAccess () const { return * p; } protected: SIfacePtr () : p (0) {} void Free () if ( p != 0) p->Release (); p = 0; T * p; private: SIfacePtr (SIfacePtr const & p) {} void operator = (SIfacePtr const & p) {} Не волнуйте, что этот класс выглядит непригодным (потому что имеет защищенный конструктор). Мы никогда не будем использовать его непосредственно. Мы наследуем от него. Между прочим, это удобный прием: создайте класс с защищенным пустым конструктором, и осуществите наследование от него. Все наследующие классы должны обеспечивать их внутреннюю реализацию своими открытыми конструкторами. Поскольку вы можете иметь различные классы, наследующие от SIfacePtr, они будут отличаться по способу получения, по их конструкторам, рассматриваемым интерфейсам. Закрытый фиктивный копирующий конструктор и оператор = не всегда необходимы, но они сохранят вам время, потраченное на отладку, если по ошибке вы передадите интеллектуальный интерфейс по значению вместо передачи по ссылке. Это больше невозможно. Вы можете освободить один и тот же интерфейс, дважды и это будет круто отражаться на подсчете ссылок COM. Верьте, это случается. Как это часто бывает, компилятор откажется передавать по значению объект, который имеет закрытую копию конструктора. Он также выдаст ошибку, когда вы пробуете присвоить объект, который имеет закрытый оператор присваивания. Оболочки API часто распределяет память, используя свои собственные специальные программы распределения. Это не было бы настолько плохо, если бы не предположение, что они ожидают от вас освобождения памяти с использованием той же самой программы распределения. Так, всякий раз, когда оболочка вручает нам такой сомнительный пакет, мы оборачиваем его в специальный интеллектуальный указатель. template <class T> class SShellPtr public: ~SShellPtr () Free (); malloc->Release (); T * weak operator->() { return p; } T const * operator->() const { return p; } operator T const * () const { return p; } T const & GetAccess () const { return * p; } protected: SShellPtr () : p (0) Obtain malloc here, rather than in the destructor. Destructor must be fail-proof. Revisit: Would static IMalloc * shellMalloc work? if (SHGetMalloc (& malloc) == E FAIL) throw Exception Couldnt obtain Shell Malloc ; void Free () if ( p != 0) malloc->Free ( p); p = 0; T * p; IMalloc * malloc; private: SShellPtr (SShellPtr const & p) {} void operator = (SShellPtr const & p) {} Обратите внимание на использование приема: класс SShellPtr непосредственно не пригоден для использования. Вы должны наследовать от него подкласс и реализовать в нем соответствующий конструктор. Обратите также внимание, нет уверенности, может ли shellMalloc быть статическим элементом SShellPtr. Проблема состоит в том, что статические элементы инициализируются перед WinMain. Из-за этого вся COM система может оказаться неустойчивой. С другой стороны, документация говорит, что вы можете безопасно вызывать из другой API функции CoGetMalloc перед обращением к Colnitialize. Это не говорит о том, может ли SHGetMalloc, который делает почти то же самое, также вызываться в любое время в вашей программе. Подобно многим другим случаям, когда система ужасно разработана или задокументирована, только эксперимент может ответить на такие вопросы. Между прочим, если вы нуждаетесь в интеллектуальном указателе, который использует специфическое распределение памяти для COM, то получите его, вызывая CoGetMalloc. Вы можете без опаски сделать этот malloc статическим элементом и инициализировать его только один раз в вашей программе (ниже SComMalloc:: GetMalloc тоже статический): IMalloc * SComMalloc:: malloc = SComMalloc::GetMalloc (); IMalloc * SComMalloc::GetMalloc () { IMalloc * malloc = 0; if (CoGetMalloc (1, & malloc) == S OK) return malloc; else return 0; Это - все, что надо знать, чтобы начать использовать оболочку Windows и ее COM интерфейсы. Ниже приводится
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |