Студопедия КАТЕГОРИИ: АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Недостатки обычных – «неумных» – указателей.
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, а примеры использования – в данной работе (см. раздел «Применение интеллектуальных указателей для доступа к серверам»). Управление формой курсора мыши В простейшем случае, если надо показать «песочные часы», можно поступить так: BeginWaitCursor(); // долго с чем-то возимся EndWaitCursor(); Другие подробности – в MSDN, причем совсем задаром.
Как выйти из длительного цикла Если какая-либо функция приложения выполняется длительное время, полезно предоставить пользователю возможность ее остановки. Если приложение однопоточное, то можно написать примерно такую функцию: void CMyView::ProcessMessages() { MSG msg; while(::PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } }
Вызов этой функции надо поместить в тот самый длительный цикл для того, чтобы пользователь мог нажать какую-нибудь кнопку приложения и оно на это действие отреагировало. Если же приложение многопоточное, то при нажатии пользователем кнопки завершения приложения (в системном меню – правом верхнем углу главного окна приложения) может появиться сообщение об ошибке. Ваше приложение может быть многопоточным даже и в том случае, если Вы и не создаете «в лоб» дополнительный поток, например, просто строите приложение на основе классов CRichEditCtrlItem и CRichEditView. В подобном случае можно поступить следующим образом. Перекройте виртуальную функцию WindowProc(), например, класса вида, такой реализацией: LRESULT CMyView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { Stop=(message==257)&(wParam==27); return CView::WindowProc(message, wParam, lParam); }
В ней магическое число 27 – это код клавиши Escape, а Stop – переменная булевского типа, которую Вы описали в своем же классе CMyView и изначально присвоили ей значение false. Функция WindowProc() обрабатывает все сообщения, которые Windows посылает, в данном примере, окну вида приложения. Следовательно, если пользователь нажмет клавишу Escape, то переменная Stop примет значение true, которое можно проанализировать в длительном цикле и выйти из него. Не забудьте в этом цикле вызывать функцию ProcessMessages.
|
||
Последнее изменение этой страницы: 2018-04-12; просмотров: 407. stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда... |