Чтение онлайн

на главную - закладки

Жанры

Применение Windows API

Легалов А. И.

Шрифт:

class Controller {

public:

 Controller(HWND hwnd, CREATESTRUCT * pCreate);

 ~Controller;

 // … private:

 UseCom _comUser; // i'm a com user

 Model _model;

 View _view;

 HINSTANCE _hInst;

};

Этот способ гарантируют, что COM подсистема будет проинициализирована прежде, чем к ней будут сделаны

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

Класс UseCom очень прост.

class UseCom {

public:

 UseCom {

HRESULT err = CoInitialize(0);

if (err != S_OK) throw "Couldn't initialize COM";

 }

 ~UseCom {

CoUninitialize;

 }

};

Пока не было слишком трудно, не так ли? Дело в том, что мы не коснулись главной мерзости COM программирования — подсчета ссылок. Вам должно быть известно, что каждый раз, когда что Вы получаете интерфейс, его счетчик ссылок увеличивается. И Вам необходимо явно уменьшать его. И это становится более чем ужастным тогда, когда Вы начинаете запрашивать интерфейсы, копировать их, передавать другим и т.д. Но ловите момент: мы знаем, как управляться с такими проблемами! Это называется управлением ресурсами. Мы никогда не должны касаться интерфейсов COM без инкапсуляции их в интеллектуальных указателях на интерфейсы. Ниже показано, как это работает.

Примечание. В настоящий момент данная тема достаточно широко рассмотрена в литературе, переведенной на русский язык. В частности, можно отметить книги:

Джефф Элджер. "C++: библиотека программиста";

Скотт Мейерс. "Эффективное программирование на С++".

А.Л.

template <class T>

class SIfacePtr {

public:

 ~SIfacePtr {

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 "Couldn't 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 непосредственно не пригоден для использования. Вы должны наследовать от него подкласс и реализовать в нем соответствующий конструктор.

Поделиться:
Популярные книги

Черный дембель. Часть 5

Федин Андрей Анатольевич
5. Черный дембель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Черный дембель. Часть 5

30 сребреников

Распопов Дмитрий Викторович
1. 30 сребреников
Фантастика:
попаданцы
альтернативная история
фэнтези
фантастика: прочее
5.00
рейтинг книги
30 сребреников

Жребий некроманта 2

Решетов Евгений Валерьевич
2. Жребий некроманта
Фантастика:
боевая фантастика
6.87
рейтинг книги
Жребий некроманта 2

Охота на разведенку

Зайцева Мария
Любовные романы:
современные любовные романы
эро литература
6.76
рейтинг книги
Охота на разведенку

Чужбина

Седой Василий
2. Дворянская кровь
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Чужбина

Возвышение Меркурия. Книга 4

Кронос Александр
4. Меркурий
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Возвышение Меркурия. Книга 4

Надуй щеки! Том 3

Вишневский Сергей Викторович
3. Чеболь за партой
Фантастика:
попаданцы
дорама
5.00
рейтинг книги
Надуй щеки! Том 3

Идеальный мир для Лекаря 16

Сапфир Олег
16. Лекарь
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 16

По воле короля

Леви Кира
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
По воле короля

Он тебя не любит(?)

Тоцка Тала
Любовные романы:
современные любовные романы
7.46
рейтинг книги
Он тебя не любит(?)

Курсант: назад в СССР 9

Дамиров Рафаэль
9. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: назад в СССР 9

Штуцер и тесак

Дроздов Анатолий Федорович
1. Штуцер и тесак
Фантастика:
боевая фантастика
альтернативная история
8.78
рейтинг книги
Штуцер и тесак

Камень Книга седьмая

Минин Станислав
7. Камень
Фантастика:
фэнтези
боевая фантастика
6.22
рейтинг книги
Камень Книга седьмая

Хозяйка дома в «Гиблых Пределах»

Нова Юлия
Любовные романы:
любовно-фантастические романы
5.75
рейтинг книги
Хозяйка дома в «Гиблых Пределах»