MFC类库CArray类模板源代码注释及在Win32 控制台程序中的简单使用.doc_第1页
MFC类库CArray类模板源代码注释及在Win32 控制台程序中的简单使用.doc_第2页
MFC类库CArray类模板源代码注释及在Win32 控制台程序中的简单使用.doc_第3页
MFC类库CArray类模板源代码注释及在Win32 控制台程序中的简单使用.doc_第4页
MFC类库CArray类模板源代码注释及在Win32 控制台程序中的简单使用.doc_第5页
免费预览已结束,剩余6页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2010年9月14日16:58:44新建一个Win32控制台程序,使用MFC类库。工程设置:点击菜单“Project”“Settings”,选择“General”标签,在“Microsoft Foundation Classes”组合框下,选择“Use MFC in a Shared DLL”。以静态链接库的形式使用MFC类库。源程序如下:#include#include#include int main()CArray m_array;/定义数组对象CPoint pt1(10,10);/定义对象并存放在数组中m_array.Add(pt1);CPoint pt2(20,20);m_array.Add(pt2);CPoint pt3(30,30);m_array.Add(pt3);int size=m_array.GetSize();/获取数组实际大小-元素个数CPoint pt;int index=0;for(index=0;indexsize;index+)/输出数组元素pt=m_array.GetAt(index);coutpt.x pt.yendl;return 0;测试:输出成功。2010年9月14日17:04:12下面是CArray的定义。参考MSDN进行理解。模板参数TYPE指出了存放在CArray中的对象的类型。两个模板参数暂时认为应该一样。/ CArraytemplateclass CArray : public CObjectpublic:/ ConstructionCArray();/ Attributesint GetSize() const;int GetUpperBound() const;void SetSize(int nNewSize, int nGrowBy = -1);/ Operations/ Clean upvoid FreeExtra();void RemoveAll();/ Accessing elementsTYPE GetAt(int nIndex) const;void SetAt(int nIndex, ARG_TYPE newElement);TYPE& ElementAt(int nIndex);/ Direct Access to the element data (may return NULL)const TYPE* GetData() const;TYPE* GetData();/ Potentially growing the arrayvoid SetAtGrow(int nIndex, ARG_TYPE newElement);int Add(ARG_TYPE newElement);int Append(const CArray& src);void Copy(const CArray& src);/ overloaded operator helpersTYPE operator(int nIndex) const;TYPE& operator(int nIndex);/ Operations that move elements aroundvoid InsertAt(int nIndex, ARG_TYPE newElement, int nCount = 1);void RemoveAt(int nIndex, int nCount = 1);void InsertAt(int nStartIndex, CArray* pNewArray);/ Implementationprotected:TYPE* m_pData; / the actual array of data/保存实际数组的指针int m_nSize; / # of elements (upperBound - 1)/数组的元素个数int m_nMaxSize; / max allocated/数组的容量大小int m_nGrowBy; / grow amountpublic:CArray();void Serialize(CArchive&);#ifdef _DEBUGvoid Dump(CDumpContext&) const;void AssertValid() const;#endif;/构造函数的实现templateCArray:CArray()/数据成员初始化,空数组m_pData = NULL;m_nSize = m_nMaxSize = m_nGrowBy = 0;typedef unsigned char BYTE;/1个字节/析构函数的实现templateCArray:CArray()ASSERT_VALID(this);if (m_pData != NULL)DestructElements(m_pData, m_nSize);/释放元素-调用析构函数/数组容量未保存元素的部分不存在对象,所以不用调用析构函数,但要释放内存delete (BYTE*)m_pData;/释放内存#ifndef AFX_INLINE#define AFX_INLINE inline /*_forceinline*/#endif/返回数组的元素个数m_nSizetemplateAFX_INLINE int CArray:GetSize() const return m_nSize; /返回数组的上限下标(元素个数-1)templateAFX_INLINE int CArray:GetUpperBound() const return m_nSize-1; /返回数组在指定下标的元素,应该是拷贝。不准对数组进行修改。/首先对参数进行检查。出错会怎么处理。好像程序直接崩溃。不可取。templateAFX_INLINE TYPE CArray:GetAt(int nIndex) const ASSERT(nIndex = 0 & nIndex m_nSize);return m_pDatanIndex; /拷贝构造函数/在数组的指定下标保存输入对象。也应该是拷贝/引用传值比较好/首先对参数进行检查。templateAFX_INLINE void CArray:SetAt(int nIndex, ARG_TYPE newElement) ASSERT(nIndex = 0 & nIndex m_nSize);m_pDatanIndex = newElement; /赋值操作符/返回数组指定下标元素的引用-不是指针。可以从该元素获取数据,也可以对该元素修改数据。AFX_INLINE TYPE& CArray:ElementAt(int nIndex) ASSERT(nIndex = 0 & nIndex m_nSize);return m_pDatanIndex; /返回实际数组的常量指针。可获取数据,但不能修改数据templateAFX_INLINE const TYPE* CArray:GetData() const return (const TYPE*)m_pData; /返回实际数组的指针。可获取数据,也能修改数据templateAFX_INLINE TYPE* CArray:GetData() return (TYPE*)m_pData; 上面这两组,调用时怎么区别?在尾部加const的对象成员函数,就是在this指针前加一个const,该对象成员函数不能修改this指针指向的对象,也不能调用非const对象成员函数。const对象只能调用const函数;非const对象优先调用非const成员函数,没有非const成员函数,则调用const成员函数。我一般不喜欢使用const成员函数。/数组操作符的两组函数,调用时怎么区别。同上/返回数组在指定下标的元素,应该是拷贝。不准对数组进行修改。templateAFX_INLINE TYPE CArray:operator(int nIndex) const return GetAt(nIndex); /拷贝构造函数/返回数组指定下标元素的引用-不是指针。可以从该元素获取数据,也可以对该元素修改数据。templateAFX_INLINE TYPE& CArray:operator(int nIndex) return ElementAt(nIndex); /设置数组元素个数不是容量大小templatevoid CArray:SetSize(int nNewSize, int nGrowBy)/检查参数ASSERT_VALID(this);ASSERT(nNewSize = 0);/新步长=0,则更新步长,否则忽略if (nGrowBy != -1)m_nGrowBy = nGrowBy; / set new sizeif (nNewSize = 0)/新的数组大小为0/ shrink to nothingif (m_pData != NULL)/释放元素、释放内存DestructElements(m_pData, m_nSize);/调用析构函数/数组容量未保存元素的部分不存在对象,所以不用调用析构函数,但要释放内存delete (BYTE*)m_pData;m_pData = NULL;m_nSize = m_nMaxSize = 0;/数组容量和数组元素大小都为0else if (m_pData = NULL)/原来数组无元素,现在要求有元素/ create one with exact size#ifdef SIZE_T_MAX/大小检查ASSERT(nNewSize = SIZE_T_MAX/sizeof(TYPE); / no overflow#endif/动态分配一块内存m_pData = (TYPE*) new BYTEnNewSize * sizeof(TYPE);/构造元素ConstructElements(m_pData, nNewSize);/调用默认构造函数m_nSize = m_nMaxSize = nNewSize;/数组大小=数组元素个数-数组满员else if (nNewSize =新的数组元素个数/ it fitsif (nNewSize m_nSize)/新的元素个数数组元素个数,则构造新的元素来满足要求/ initialize the new elements/调用默认构造函数ConstructElements(&m_pDatam_nSize, nNewSize-m_nSize);else if (m_nSize nNewSize)/新的元素个数数组元素个数,则释放多余的元素来满足要求/ destroy the old elements/调用析构函数DestructElements(&m_pDatanNewSize, m_nSize-nNewSize);m_nSize = nNewSize;/数组元素个数=输入参数,数组容量可能不满员else/原来数组的容量大小新的数组元素个数-增加内存/ otherwise, grow arrayint nGrowBy = m_nGrowBy;if (nGrowBy = 0)/当步长为0时,MFC计算出一个步长/ heuristically determine growth when nGrowBy = 0/ (this avoids heap fragmentation in many situations)nGrowBy = m_nSize / 8;nGrowBy = (nGrowBy 1024) ? 1024 : nGrowBy);/计算新实际数组的容量大小int nNewMax;if (nNewSize = m_nMaxSize); / no wrap around#ifdef SIZE_T_MAX/动态分配内存的大小限制ASSERT(nNewMax m_nSize);/构造新的元素也满足新元素个数要求/调用默认构造函数ConstructElements(&pNewDatam_nSize, nNewSize-m_nSize);/ get rid of old stuff (note: no destructors called)/无需调用析构函数,从对象数目来分析delete (BYTE*)m_pData;/释放原来实际数组占用的内存m_pData = pNewData;/实际数组新的地址m_nSize = nNewSize;/新的元素个数=参数要求的元素个数m_nMaxSize = nNewMax;/数组新的容量大小/从SetSize的代码中可以知道,数组完全管理元素的内存,为元素分配内存,拷贝,释放元素所占的内存。/除了输入参数为0时,数组容量被释放。其它情况,数组容量不变或增大。/扩展数组,将输入数组的所有元素增加到数组的后面templateint CArray:Append(const CArray& src)ASSERT_VALID(this);ASSERT(this != &src); / cannot append to itselfint nOldSize = m_nSize;SetSize(m_nSize + src.m_nSize);/设置数组元素个数为两数组元素之和/使用赋值操作符拷贝,从源数组拷贝n个对象到目的数组CopyElements(m_pData + nOldSize, src.m_pData, src.m_nSize);return nOldSize;/返回this数组原来的元素个数/拷贝输入数组到this数组,数组新的元素个数为输入数组的元素个数templatevoid CArray:Copy(const CArray& src)ASSERT_VALID(this);ASSERT(this != &src); / cannot append to itselfSetSize(src.m_nSize); /数组新的元素个数为输入数组的元素个数/将输入数组的元素拷贝到this数组/使用赋值操作符拷贝,从源数组拷贝n个对象到目的数组CopyElements(m_pData, src.m_pData, src.m_nSize); /在指定下标拷贝输入元素,/使用引用传值比较好templatevoid CArray:SetAtGrow(int nIndex, ARG_TYPE newElement)ASSERT_VALID(this);ASSERT(nIndex = 0);if (nIndex = m_nSize)/如果下标=元素个数,则设置元素个数为nIndex+1SetSize(nIndex+1, -1);m_pDatanIndex = newElement;/在指定下标拷贝输入元素/赋值操作符/压缩数组,使数组容量大小=数组元素个数templatevoid CArray:FreeExtra()ASSERT_VALID(this);if (m_nSize != m_nMaxSize)/数组容量大小不等于数组元素个数/ shrink to desired size#ifdef SIZE_T_MAX/检查分配内存的大小ASSERT(m_nSize 0/动态分配内存pNewData = (TYPE*) new BYTEm_nSize * sizeof(TYPE);/ copy new data from old/从旧实际数组拷贝所有元素到新的实际数组简单拷贝/拷贝前后,元素(对象)的数目不变memcpy(pNewData, m_pData, m_nSize * sizeof(TYPE);/ get rid of old stuff (note: no destructors called) /元素(对象)的数目不变delete (BYTE*)m_pData;/将旧实际数组所占内存释放-简单释放,不调用析构函数m_pData = pNewData;/新的实际数组指针m_nMaxSize = m_nSize;/数组容量大小=数组元素个数/从指定nIndex下标起连续插入count次输入元素(全一样),根据原来数组元素个数,与输入的参数:下标、拷贝次数,进行分情况讨论。/引用传值比较好templatevoid CArray:InsertAt(int nIndex, ARG_TYPE newElement, int nCount /*=1*/)/首先是参数检查ASSERT_VALID(this);ASSERT(nIndex = 0); / will expand to meet needASSERT(nCount 0); / zero or negative size not allowedif (nIndex = m_nSize)/插入下标数组上限下标,没有数据移动/ adding after the end of the arraySetSize(nIndex + nCount, -1); / grow so nIndex is validelse/插入下标=数组上限下标,有数据移动/ inserting in the middle of the arrayint nOldSize = m_nSize;/设置数组元素个数增大nCountSetSize(m_nSize + nCount, -1); / grow it to new size/ destroy intial data before copying over it/释放末尾新增的nCount个元素/调用析构函数DestructElements(&m_pDatanOldSize, nCount);/ shift old data up to fill gap/插入引起的数据移动/从前往后移/无须调用对应类型的拷贝函数,移动前后只有一份对象memmove(&m_pDatanIndex+nCount, &m_pDatanIndex,(nOldSize-nIndex) * sizeof(TYPE);/ re-init slots we copied from/从下标 nIndex起,构造nCount个元素/调用默认构造函数ConstructElements(&m_pDatanIndex, nCount); / insert new value in the gap/要求拷贝元素的下标=数组元素个数-1ASSERT(nIndex + nCount = m_nSize);while (nCount-)/赋值操作符m_pDatanIndex+ = newElement;/从nIndex下标起连续拷贝count个元素(全一样)我不知道构造元素和释放元素的作用是什么。-调用对应类型的默认构造函数和析构函数/从nIndex下标起移走nCount个元素templatevoid CArray:RemoveAt(int nIndex, int nCount)/参数检查ASSERT_VALID(this);ASSERT(nIndex = 0);ASSERT(nCount = 0);ASSERT(nIndex + nCount = m_nSize);/ just remove a rangeint nMoveCount = m_nSize - (nIndex + nCount);/释放nIndex下标起的nCount个元素DestructElements(&m_pDatanIndex, nCount);/调用析构函数if (nMoveCount)/插入引起的数据移动-从后往前移/无须调用对应类型的拷贝函数,移动前后只有一份对象memmove(&m_pDatanIndex, &m_pDatanIndex + nCount,nMoveCount * sizeof(TYPE);m_nSize -= nCount;/数组元素个数变小,但容量不变,移动的元素原来的区域没有释放/从下标nStartIndex起,插入数组pNewArraytemplatevoid CArray:InsertAt(int nStartIndex, CArray* pNewArray)/数据检查ASSERT_VALID(this);ASSERT(pNewArray != NULL);ASSERT_VALID(pNewArray);ASSERT(nStartIndex = 0);if (pNewArray-GetSize() 0)/输入数组的元素个数0/从下标nStartIndex起,插入n次输入数组的第一个元素InsertAt(nStartIndex, pNewArray-GetAt(0), pNewArray-GetSize();/从下标nStartIndex(+1)起拷贝输入数组的元素for (int i = 0; i GetSize(); i+)SetAt(nStartIndex + i, pNewArray-GetAt(i);/清空数组,使数组元素个数为0templateAFX_INLINE void CArray:RemoveAll() SetSize(0, -1); /在实际数组后面增加一个元素,数组元素个数加1templateAFX_INLINE int CArray:Add(ARG_TYPE newElement) int nIndex = m_nSize;SetAtGrow(nIndex, newElement);return nIndex; 2010年9月14日20:57:16模板函数:析构数组元素。调用对应类型的析构函数。数组位置由输入指针确定,数组大小由输入数组大小确定。templateAFX_INLINE void AFXAPI DestructElements(TYPE* pElements, int nCount)ASSERT(nCount = 0 |AfxIsValidAddress(pElements, nCount * sizeof(TYPE);/ call the destructor(s)for (; nCount-; pElements+)pElemen

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论