1 / 162

Chap. 4

Chap. 4. Utility Classes. Contents. Simple value types 일반적 목적 : CString, CTime, CTimeSpan 윈도우 구조체 : CPoint, CSize, Crect MFC collection classes array, linked list, map CFile class family CException class. Introduction. 우리가 만드는 많은 class 들 Utility class 의 범주에 든다. 이 단원의 목적

kiley
Download Presentation

Chap. 4

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chap. 4 Utility Classes

  2. Contents • Simple value types • 일반적 목적 : CString, CTime, CTimeSpan • 윈도우 구조체 : CPoint, CSize, Crect • MFC collection classes • array, linked list, map • CFile class family • CException class

  3. Introduction • 우리가 만드는 많은 class들 • Utility class의 범주에 든다. • 이 단원의 목적 • MFC 개발자 들의 technique • 앞으로의 project에 도움

  4. Simple Value Types • Simple value types • C++ type(char*, …), Windows type(RECT, …) 들을 encapsulating 한 클래스들 • C++ interface 제공 • 더 안전하고 더 쉽게 이용할 수 있는 operator 제공 • memory management • internationalization • …

  5. Class CString • Character string을 encapsulate함 • 다음과 같은 특징이 있음 • Internationalization • Memory allocation/deallocation • Operators(+, =, ==, …) • String searching • String manipulation(reverse, concat) • Formatting(printf-like)

  6. Using a CString • 생성 // create a CString from a char * CString myString1(“This is a string”); // create a CString from a CString CString myString2(myString1); // create a CString with 80 z characters CString myString3(‘z’, 80); // create a CString as empty CString CString myString4;

  7. Using a CString (cont’d) CString myString1(“string 1”); CString myString2(“string 2”); CString myString3(“string 3”); // addition (concatenation) & assignment myString1 += myStrig2; myString3 = “This is “ + myString2; myString2 += ‘Z’; // comparison : == , < , != , … if ( myString1 == myString2 ) // like strcmp // operator[] : 0-based if ( myString1[7] == ‘l’ ) // find : Find(), FindOneOf(), ReverseFind()

  8. CString Internals • CString declaration(AFX.H) class CString { public: // Constructors CString(); CString(const CString& stringSrc); CString(TCHAR ch, int nRepeat = 1); CString(LPCSTR lpsz); CString(LPCWSTR lpsz); CString(LPCSTR lpch, int nLength); CString(LPCWSTR lpch, int nLength); CString(const unsigned char* psz);

  9. CString Internals (cont’d) // Attributes & Operations int GetLength() const; BOOL IsEmpty() const; void Empty(); TCHAR GetAt(int nIndex) const; TCHAR operator[](int nIndex) const; void SetAt(int nIndex, TCHAR ch); operator LPCTSTR() const; const CString& operator=(const CString& stringSrc); const CString& operator=(TCHAR ch); const CString& operator=(LPCSTR lpsz); const CString& operator=(LPCWSTR lpsz); const CString& operator=(const unsigned char* psz);

  10. CString Internals (cont’d) // concatenate const CString& operator+=(const CString& string); const CString& operator+=(TCHAR ch); const CString& operator+=(LPCTSTR lpsz); friend CString AFXAPI operator+(const CString& string1, const CString& string2); friend CString AFXAPI operator+(const CString& string, TCHAR ch); friend CString AFXAPI operator+(TCHAR ch, const CString& string); friend CString AFXAPI operator+(const CString& string, LPCTSTR lpsz); friend CString AFXAPI operator+(LPCTSTR lpsz, const CString& string); // string comparison int Compare(LPCTSTR lpsz) const; int CompareNoCase(LPCTSTR lpsz) const; int Collate(LPCTSTR lpsz) const; int CollateNoCase(LPCTSTR lpsz) const;

  11. CString Internals (cont’d) // simple sub-string extraction CString Mid(int nFirst, int nCount) const; CString Mid(int nFirst) const; CString Left(int nCount) const; CString Right(int nCount) const; CString SpanIncluding(LPCTSTR lpszCharSet) const; CString SpanExcluding(LPCTSTR lpszCharSet) const; // upper/lower/reverse conversion void MakeUpper(); void MakeLower(); void MakeReverse(); // advanced manipulation int Replace(TCHAR chOld, TCHAR chNew); int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew); int Remove(TCHAR chRemove); int Insert(int nIndex, TCHAR ch); int Insert(int nIndex, LPCTSTR pstr); int Delete(int nIndex, int nCount = 1);

  12. CString Internals (cont’d) // searching int Find(TCHAR ch) const; int ReverseFind(TCHAR ch) const; int Find(TCHAR ch, int nStart) const; int FindOneOf(LPCTSTR lpszCharSet) const; int Find(LPCTSTR lpszSub) const; int Find(LPCTSTR lpszSub, int nStart) const; // simple formatting void AFX_CDECL Format(LPCTSTR lpszFormat, ...); void AFX_CDECL Format(UINT nFormatID, ...); void FormatV(LPCTSTR lpszFormat, va_list argList); // input and output friend CArchive& AFXAPI operator<<(CArchive& ar, const CString& string); friend CArchive& AFXAPI operator>>(CArchive& ar, CString& string); // load from string resource BOOL LoadString(UINT nID);

  13. CString Internals (cont’d) // get pointer to modifiable buffer at least as long as nMinBufLength LPTSTR GetBuffer(int nMinBufLength); // release buffer, setting length to nNewLength (or to first nul if -1) void ReleaseBuffer(int nNewLength = -1); // get pointer to modifiable buffer exactly as long as nNewLength LPTSTR GetBufferSetLength(int nNewLength); // release memory allocated to but unused by string void FreeExtra(); // turn refcounting back on LPTSTR LockBuffer(); // turn refcounting off void UnlockBuffer(); // Implementation public: ~CString(); int GetAllocLength() const;

  14. CString Internals (cont’d) protected: LPTSTR m_pchData; // pointer to ref counted string data // implementation helpers CStringData* GetData() const; void Init(); void AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const; void AllocBuffer(int nLen); void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData); void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data); void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData); void CopyBeforeWrite(); void AllocBeforeWrite(int nLen); static void PASCAL Release(CStringData* pData); static int PASCAL SafeStrlen(LPCTSTR lpsz); static void FASTCALL FreeData(CStringData* pData); };

  15. CString Internals (cont’d) • CString declaration(AFX.H) • m_pchData • 유일한 멤버 변수 • String에 대한 pointer • CStringData • CString의 기능 구현을 도와주는 structure struct CStringData { long nRefs; // reference count int nDataLength; // length of data (including terminator) int nAllocLength; // length of allocation TCHAR* data() // TCHAR* to managed data { return (TCHAR*)(this+1); } };

  16. CString Internals (cont’d) • 공간 할당 함수 AllocBuffer()(STRCORE.CPP) void CString::AllocBuffer(int nLen) { if (nLen == 0) Init(); else { CStringData* pData = (CStringData*)newBYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)]; pData->nAllocLength = nLen; pData->nRefs = 1; pData->data()[nLen] = '\0'; pData->nDataLength = nLen; m_pchData = pData->data(); } }

  17. CStringData Data(nlength + 1) nRefs nDataLength nAllocLength CString::m_pchData CString Internals (cont’d) • AllocBuffer()함수에 의한 memory 할당

  18. CString Internals (cont’d) • 의문점 • CString class는 string 이외의 데이터를 숨김 • 왜, 그들을 멤버변수로 추가하지 않았는가 • CString object와 TCHAR *은 똑같아야 한다. • same bits • 그 이외의 부가적인 정보는 CStringData 에서 관리 • 이전 버전과의 호환성

  19. CString Internals (cont’d) • Reference counting • CStringData::nRefs • 실제 데이터의 변경이 가해지면 copy CString myString1(“This is a string”); CString myString2(myString1); CString myString3 = myString1; myString2 myString1 “This is a string” myString3

  20. CString Internals (cont’d) • Reference counting 과정 • nRefs 변수의 값이 -1 으로 초기화 • 그 string에 새 참조가 발생하면 1 증가 • 참조가 줄어들면 1 감소 • 다시 0이 되면 삭제 가능 • 참조되는 string에 쓰기가 발생하면 새로운 string을 생성하고 원래의 string의 nRefs값을 1 감소 • Critical resource • 일종의 OS에서 발생하는 resource 공유 문제 • 두 thread 에서 동시에 참조를 증가 혹은 감소시키는 경우 문제 해결 • InterlockedIncrement(), InterlockedDecrement()

  21. CString Internals (cont’d) • 예제 Line 1 Line 2 Line 3 Line 4 Line 5 CString myString1(“This is mystring1”); CString myString2(myString1); CString myString3; myString3 = myString2; // Write somthing myString3.MakeUpper();

  22. CString Internals (cont’d) “Strcore.cpp” CString::CString(LPCTSTR lpsz) { int nLen = SafeStrlen(lpsz); if (nLen != 0) { AllocBuffer(nLen); memcpy(m_pchData, lpsz, nLen*sizeof(TCHAR)); } } myString1 “This is my string1” 1

  23. CString Internals (cont’d) CString::CString(const CString& stringSrc) { if (stringSrc.GetData()->nRefs >= 0) { m_pchData = stringSrc.m_pchData; InterlockedIncrement(&GetData()->nRefs); } else { Init(); *this = stringSrc.m_pchData; } } myString1 “This is my string1” 2 myString2

  24. CString Internals (cont’d) const CString& CString::operator=(const CString& stringSrc) { if (m_pchData != stringSrc.m_pchData) { if ((GetData()->nRefs < 0 && GetData() != _afxDataNil) || stringSrc.GetData()->nRefs < 0) { // actual copy necessary since one of the strings is locked AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData); } else { // can just copy references around Release(); m_pchData = stringSrc.m_pchData; InterlockedIncrement(&GetData()->nRefs); } } return *this; } myString2 myString1 “This is my string1” 3 myString3

  25. CString Internals (cont’d) void CString::MakeUpper() { CopyBeforeWrite(); _tcsupr(m_pchData); } void CString::CopyBeforeWrite() { if (GetData()->nRefs > 1) { CStringData* pData = GetData(); Release(); AllocBuffer(pData->nDataLength); memcpy(m_pchData,pData->data(), (pData->nDataLength+1)*sizeof (TCHAR)); } ASSERT(GetData()->nRefs <= 1); }

  26. CString Internals (cont’d) void CString::Release() { if (GetData() != _afxDataNil) { ASSERT(GetData()->nRefs != 0); if (InterlockedDecrement(&GetData()->nRefs) <= 0) FreeData(GetData()); Init(); } } myString1 “This is my string1” 2 myString2 myString3 “THIS IS MY STRING1” 1

  27. CString Internals (cont’d) • Internationalization • _t internationalized string 함수를 이용하여 구현 • _tcschr() => strchr() mapping int CString::Find(TCHAR ch, int nStart) const { int nLength = GetData()->nDataLength; if (nStart >= nLength) return -1; LPTSTR lpsz = _tcschr(m_pchData + nStart, (_TUCHAR)ch); return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); }

  28. Other Simple Value Types

  29. Class CRect • Declaration (AFXWIN.H) class CRect : public tagRECT { … typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom; } RECT;

  30. Class CRect (cont’d) void CRect::DeflateRect(LPCRECT lpRect) { left += lpRect->left; top += lpRect->top; right -= lpRect->right; bottom -= lpRect->bottom; }

  31. MFC Collection Classes • MFC collection classes • Array • 일반적인 C++에서의 array임 • 단 모든 메모리관련 기능 추가 • List • Doubly linked list • Map • 일종의 dictionary • Key, value 쌍으로 데이터를 저장

  32. Type of Collection Classes • Template-based • Nontemplate-based • Array : CObArray, CByteArray, … • List : CObList, CPtrList, CStringList • Map : CMapPtrToWord, …

  33. Shape Features

  34. Type-safe Collection • Template-based classes • 변수 선언 • 멤버 함수 호출 • 필요할 경우, helper function 구현 (CArray, CList, CMap 에서) • CompareElements • CopyElements • Dumpelements • HashKey • SerializeElements

  35. Type-safe Collection (cont’d) // 변수 선언 CList<int, int> m_intList; // 함수 호출 m_intList.AddTail( 100 ); m_intList.RemoveAll( ); // helper function 구현 class CPerson : public CObject { . . . }; CArray< CPerson, CPerson& > personArray; template <> void AFXAPI SerializeElements <CPerson> ( CArchive& ar, CPerson* pNewPersons, int nCount ) { for ( int i = 0; i < nCount; i++, pNewPersons++ ) { // Serialize each CPerson object pNewPersons->Serialize( ar ); } }

  36. Type-safe Collection (cont’d) • Nontemplate-based classes • 방법 1 : Type-casting 활용 • 방법 2 : 파생클래스 생성 class CPerson : public CObject {...}; CPerson* p1 = new CPerson(...); CObList myList; myList.AddHead( p1 ); // No cast needed CPerson* p2 = ( CPerson* )myList.GetHead(); class CPersonList : public CObList { public: void AddHeadPerson( CPerson* person ) {AddHead( person );} const CPerson* GetHeadPerson() {return (CPerson*)GetHead();} };

  37. Iteration • Array • List CTypedPtrArray<CObArray, CPerson*> myArray; for( int i = 0; i < myArray.GetSize();i++ ){ CPerson* thePerson = myArray.GetAt( i ); // CPerson* thePerson = myArray[ i ]; } CTypedPtrList<CObList, CPerson*> myList; POSITION pos = myList.GetHeadPosition(); while( pos != NULL ) { CPerson* thePerson = myList.GetNext( pos ); ... }

  38. Iteration (cont’d) • Map CMap<CString, LPCTSTR, CPerson*, CPerson*> myMap; POSITION pos = myMap.GetStartPosition(); while( pos != NULL ) { CPerson* pPerson; CString string; myMap.GetNextAssoc( pos, string, pPerson ); } CMapStringToOb myMap; // A nontemplate collection class POSITION pos = myMap.GetStartPosition( ); while( pos != NULL ) { CPerson* pPerson; CString string; myMap.GetNextAssoc( pos, string, (CObject*&)pPerson ); ASSERT( pPerson->IsKindOf( RUNTIME_CLASS( CPerson ) ) ); }

  39. Additional Structures • Stack class CTray : public CObject { ... }; class CStack : public CTypedPtrList< CObList, CTray* > { public: // Add element to top of stack void Push( CTray* newTray ) { AddHead( newTray ); } // Peek at top element of stack CTray* Peek() { return IsEmpty() ? NULL : GetHead(); } // Pop top element off stack CTray* Pop() { return RemoveHead(); } };

  40. Additional Structures (cont’d) • Queue class CPerson : public CObject { ... }; class CQueue : public CTypedPtrList< CObList, CPerson* > { public: // Go to the end of the line void AddToEnd( CPerson* newPerson ) { AddTail( newPerson ); } // End of the queue // Get first element in line CPerson* GetFromFront() { return IsEmpty() ? NULL : RemoveHead(); } };

  41. Array Collections • Array collections • CByteArray, CDWordArray, CUintArray • CObArray, CStringArray, CWordArray • AFXCOLL.H • ARRAY_X.CPP ( X : type of array ) void ArrayExample() { CUintArray myIntArray; myIntArray.SetSize(100); for ( int I=0; I<100; I++ ) myIntArray.SetAt(I, 2*I); UINT bogus = myIntArray[50]; bogus = myIntArray.GetAt(50); myIntArray.DeleteAt(50); }

  42. CWordArray Class class CWordArray : public CObject { DECLARE_SERIAL(CWordArray) public: // Attributes int GetSize() const; int GetUpperBound() const; void SetSize(int nNewSize, int nGrowBy = -1); // Operations void FreeExtra(); void RemoveAll(); WORD GetAt(int nIndex) const; void SetAt(int nIndex, WORD newElement); WORD& ElementAt(int nIndex);

  43. CWordArray Class (cont’d) // Direct Access to the element data (may return NULL) const WORD* GetData() const; WORD* GetData(); // Potentially growing the array void SetAtGrow(int nIndex, WORD newElement); int Add(WORD newElement); int Append(const CWordArray& src); void Copy(const CWordArray& src); // overloaded operator helpers WORD operator[](int nIndex) const; WORD& operator[](int nIndex); // Operations that move elements around void InsertAt(int nIndex, WORD newElement, int nCount = 1); void RemoveAt(int nIndex, int nCount = 1); void InsertAt(int nStartIndex, CWordArray* pNewArray);

  44. CWordArray Class (cont’d) // Implementation protected: WORD* m_pData; // the actual array of data int m_nSize; // # of elements (upperBound - 1) int m_nMaxSize; // max allocated int m_nGrowBy; // grow amount public: ~CWordArray(); void Serialize(CArchive&); #ifdef _DEBUG void Dump(CDumpContext&) const; void AssertValid() const; #endif protected: // local typedefs for class templates typedef WORD BASE_TYPE; typedef WORD BASE_ARG_TYPE; };

  45. CWordArray Class (cont’d) • CWordArray(ARRAY_W.CPP) • 멤버 변수 • m_pData • 저장된 데이터의 포인터 • m_nSize • Current size of array(“logical” size) • m_nMaxSize • “Physical” size • M_nGrowBy • 추가 메모리 할당시 추가 할당 크기 • SetSize()를 통한 이해

  46. CWordArray Class (cont’d) void CWordArray::SetSize(int nNewSize, int nGrowBy) { if (nGrowBy != -1) m_nGrowBy = nGrowBy; // set new size if (nNewSize == 0) { // shrink to nothing delete[] (BYTE*)m_pData; m_pData = NULL; m_nSize = m_nMaxSize = 0; } else if (m_pData == NULL) { // create one with exact size m_pData = (WORD*) new BYTE[nNewSize * sizeof(WORD)]; memset(m_pData, 0, nNewSize * sizeof(WORD)); // zero fill m_nSize = m_nMaxSize = nNewSize; }

  47. CWordArray Class (cont’d) else if (nNewSize <= m_nMaxSize) { // it fits if (nNewSize > m_nSize) { // initialize the new elements memset(&m_pData[m_nSize], 0, (nNewSize-m_nSize) * sizeof(WORD)); } m_nSize = nNewSize; } else { // otherwise, grow array int nGrowBy = m_nGrowBy; if (nGrowBy == 0) nGrowBy = min(1024, max(4, m_nSize / 8)); int nNewMax; if (nNewSize < m_nMaxSize + nGrowBy) nNewMax = m_nMaxSize + nGrowBy; // granularity else nNewMax = nNewSize; // no slush WORD* pNewData = (WORD*) new BYTE[nNewMax * sizeof(WORD)];

  48. CWordArray Class (cont’d) // copy new data from old memcpy(pNewData, m_pData, m_nSize * sizeof(WORD)); memset(&pNewData[m_nSize], 0, (nNewSize-m_nSize)*sizeof(WORD)); // get rid of old stuff (note: no destructors called) delete[] (BYTE*)m_pData; m_pData = pNewData; m_nSize = nNewSize; m_nMaxSize = nNewMax; } }

  49. CWordArray Class (cont’d) • SetSize()(ARRAY_W.CPP) • 5개의 section으로 구성 • Initialization section • Shrink-to-nothing section • First allocation section • Allocate-from-extra-space section • Grow-the-array section

  50. CWordArray Class (cont’d) • SetAt()(AFXCOLL.INL) • m_pData[nIndex] = newElement; • InsertAt()(ARRAY_W.CPP) • Array마지막에 insert하는 경우 • 메모리 할당 후 insert • Array 중간에 insert하는 경우 • 메모리 할당 후 데이터 이동작업 • Expensive  무분별한 사용을 삼가

More Related