Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
VC_Lect.doc
Скачиваний:
6
Добавлен:
01.07.2025
Размер:
15 Мб
Скачать
☆

24.6.Интеллектуальные указатели

См. Элджер

Недостатки обычных – «неумных» – указателей.

void MyFunction()

{

double *Arr;

int k=0;

Arr[k]=1.23; // ошибка: Arr не инициализирован, не выд. память

int Num=100;

Arr = new double [Num];

Arr[k]=1.23; // нет ошибки

Arr=0; // нет ошибки времени выполнения, но память потеряна

Arr[5]=0; // ошибка: Arr недействителен

Arr = new double [Num];

double *Arr2;

Arr2=Arr; // нет ошибки

delete [] Arr;

Arr2[5]=0; // ошибка: Arr2 указывает на уже освобожденную память

delete [] Arr2; // ошибка: повторное освобождение памяти

// ...

Arr = new double [Num];

Arr++;

delete Arr; // ошибка: Arr указывает не на начало выделенного блока памяти в куче

// ...

Arr = new double [Num];

// …

return; // забыли освободить память

}

Показать те же проблемы на примере класса.

Чего бы хотелось? Хотелось бы, чтобы эти ошибки невозможно было совершить или чтобы мы получали сообщение об ошибке уже на этапе компиляции (разработки) и чтобы это сообщение было наглядным и однозначно указывало на место ошибки.

template<class T>

class SmartPtr

{

private:

T* m_pPtr;

SmartPtr & operator=(const SmartPtr & rPtr) {}

public:

SmartPtr(T* pPtr)

{

ASSERT(pPtr != NULL);

m_pPtr = pPtr;

/* Если значение выражения макроса истинно, то состояние ошибки не возникает, а в противном случае выполнение программы прерывается с выводом информации о месте ошибки. Макрос ASSERT отлавливает ошибки только в том случае, если используются отладочные версии библиотеки MFC. В противном случае макрос «не работает» и не продуцирует никакого программного кода. Если же Вы хотите, чтобы выражение вычислялось в обеих версиях программы – отладочной и окончательной, – используйте макрос VERIFY вместо ASSERT. В отладочной версии макрос VERIFY ведет себя так же, как и макрос ASSERT. В окончательной версии макрос VERIFY вычисляет выражение, но не проверяет результат*/

}

~SmartPtr()

{

if(m_pPtr) delete m_pPtr;

}

T* operator->() const

{

ASSERT(m_pPtr != NULL);

return m_pPtr;

}

};

class CMyClass

{

int Value;

public:

CMyClass() {TRACE("Enter in CMyClass::CMyClass()"); Value=123;}

~CMyClass() {TRACE("Enter in CMyClass::~CMyClass()");}

int GetValue(){return Value;}

};

void MyFunc()

{

/* SmartPtr <CMyClass> Obj; ошибка: нет соответствующего конструктора

по умолчанию */

SmartPtr <CMyClass> Obj(new CMyClass);

TRACE("Obj->GetValue()=%d\n",Obj->GetValue());

CMyClass StatObj;

//Obj=&StatObj; //ошибка: невозможно получить доступ к защ. члену

/*

error C2248: 'SmartPtr<T>::operator =' : cannot access private member

declared in class 'SmartPtr<T>'

*/

SmartPtr <CMyClass> Obj2(new CMyClass);

// Obj=Obj2;//ошибка: невозможно получить доступ к защ. члену

SmartPtr <CMyClass> Obj3(&StatObj); /* возможно и это недостаток реализации

интеллектуального указателя*/

}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])

{

if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))

{

_tprintf(_T("Fatal Error: MFC initialization failed\n"));

return 1;

}

MyFunc();

_getch();

return 0;

}

Библиотека ATL среды Visual C++ содержит определения интеллектуальных указателей, используемых в клиентских приложениях, импортирующих библиотеки типов, для доступа к сервисам СОМ-серверов. Это шаблонные классы CComPtr и _com_ptr_t, описания которых можно найти в MSDN, а примеры использования – в данной работе (см. раздел «Применение интеллектуальных указателей для доступа к серверам»).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]