Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

C++. Энциклопедия пользователя - Либерти Дж.

Либерти Дж. C++. Энциклопедия пользователя — Москва, 2001. — 581 c.
Скачать (прямая ссылка): enciklopediyapolzovatelya2001.djvu
Предыдущая << 1 .. 260 261 262 263 264 265 < 266 > 267 268 269 270 271 272 .. 280 >> Следующая

Листинг 21.2. Простой интеллектуальный указатель класса____________________________________________________
template<class Itf> class CSmartPtr {
// Конструктор и деструктор public:
CSmartPtr() : m_pltf( null )
<
>
CSmartPtr ( Itf *pltf ) : m_pltf( null )
<
Store( pltf );
}
-CSmartPtr()
{
// Освобождение указателя интерфейса, если он не пустой Release () ;
>
// Экстракторы public:
// Получение базового указателя для вызовов методов Itf* operator->()
{
assert( m_pltf != null ); return m_pltf;
>
// Получение адреса основного указателя Itf** operators()
<
// Убедитесь, что предыдущий указатель освобожден Release () ; return Sm_pltf;
)
// Присваивание public:
Itf* operator=( Itf *pltf )
{
// Убедитесь, что предыдущий указатель освобожден
552
Распределенные вычисления
Часть V
Release () ;
// Сохранение нового указателя Store( pltf ); return m pltf;
>
// Тестирование контекста public:
bool operator1. ()
{
return ( mjpltf == null ) ;
}
operator bool()
{
return ( m_jpltf != null );
)
// Реализация protected:
void Release ()
{
if ( m_pltf != null ) {
m_pItf->Release(); m_pltf = null;
}
>
void Store( Itf *pltf )
{
// Сохранение нового указателя m_pltf = pltf;
// Call AddRef on the new pointer, check for null if ( m_pltf != null ) {
m_jpItf->AddRef () ¦
>
>
// Элементы реализации protected:
Itf *m_pltf;
) ;
Это самая простая форма интеллектуального указателя. Он обеспечивает присваивание из другого указателя того же самого типа и получение адреса содержащегося указателя для назначения необработанного указателя, возвращенного функцией или методом. При этом учитывается определение интеллектуального указателя, поскольку обработка AddRefQ и Release() происходит автоматически. Кроме того, поддерживается оператор ->, необходимый для обеспечения доступа к методам в содержащемся указателе. Добавляются также операторы тестирования, определяющие, содержит ли класс указатель интерфейса. Конечно, при этом также может использоваться конструктор копии.
Проблема с интеллектуальным указателем, показанным в листинге 21.2, состоит в том, что он всегда нуждается в вызовах Querylnterface() или CoCreateInstance() (или некоторых других средств), необходимых для заполнения значений:
CSroartPtr<IMyInterfасе> pMylnterace;
HRESULT hr;
hr = pSomeInterface->QueryInterface(
IID_IMyInterface,
(void**)SpMyInterface );
Будет лучше, если интеллектуальный указатель также будет обрабатывать Querylnterface(). Проблема заключается в том, что QuerylnterfaceQ возвращает HRESULT в случае неудачи. Интеллектуальный указатель должен принять решение, как выйти из этой ситуации. Самое очевидное решение — использовать исключение, но при этом появляется проблема, связанная с тем, что семантика оператора = не подразумевает обработку катастрофического отказа. Лучше всего проигнорировать отказ и предоставить программисту воз-
Глава 21
можность проверки каждого присваивания с помощью operator! или оператора bool. Конечно, класс должен запоминать последний HRESULT, что позволит программисту идентифицировать причину отказа. В листинге 21.3 содержится предложенное добавление.
Листинг 21.3. Дополнения к интеллектуальному указателю класса_________________________________________________
/* в конструкторах */
CSmartPtr( IUnknown *p0nk ) : m_pltf( null ), m_hr( E_POINTER )
{
StoreUnk( pUnk ) ;
1
/* в экстракторах */ operator IUnknown*()
{
return m_pltf;
}
/* в присваивании */
Itf* operator=( IUnknown* pUnk )
<
// Убедитесь, что предыдущий указатель освобожден Release () ;
// Сохранение нового указателя StoreUnk( pUnk ) ; return m_pltf;
}
/* при реализации */
void StoreUnk( IUnknown *pUnk )
{
if ( pUnk != null ) {
m_hr = pUnk->QueryInterface(
IID_##Itf,
(void**)&m_pltf ) ;
) else {
m_hr = E_POINTER;
)
}
/* в контексте тестирования */
HRESULT GetLastError ()
{
return m_hr;
}
/* в элементах реализации */
HRESULT m hr;
Другие конструкторы должны инициализировать элемент m_hr;- другой оператор присвоения должен установить его. Оператор Store() заканчивается этой строкой:
m_hr = (m_pltf ' = NULL ) ? S_OK : E_POINTER;
В целях непротиворечивости метод ReleaseO должен завершить оператор if следующей строкой:
m_hr = Е_РОINTER;
E_POINTER выделяется для того, чтобы указывать на ошибку, если содержащийся указатель будет иметь значение NULL.
Обратите внимание на то, что этот шаблон класса вызывает проблемы, когда выполняется образование для интерфейса IUnknown. Существуют два конструктора и два оператора присваивания, имеющие одни и те же параметры. Для разрешения этой неоднозначности должна быть исключена оптимизация AddRef(), и только для версии с IUnknown*, поскольку параметр должен оставаться. Шаблон может никогда не образовываться для IUnknown, однако он может быть приемлем.
554
Распределенные вычисления
Часть V
Использование подобного механизма улучшило работу интеллектуального указателя. Фрагмент программного кода, описанный ранее, теперь выглядит следующим образом:
HRESULT hr;
Предыдущая << 1 .. 260 261 262 263 264 265 < 266 > 267 268 269 270 271 272 .. 280 >> Следующая