5.常用函数举例 (1) 数组 如int 数组: CArray<int,int> m_intArray; m_intArray.Add(15); // 添加一个元素 CArray<CPoint,CPoint> pArray; pArray.Add(CPoint(10,10)); l 添加元素 注意,此时开始并没有分配数组的存储空间,但是add可以动态分配空间。如果可以预计数组大小,可以先用SetSize()来分配空间,因为如果频繁使用add,会产生内存碎片。SetSize可以增加数组元素,也可以减少,但是在减少时,并不会自动缩小保存数组数据的缓冲区,还是先调用removeAt先把元素删掉。 推荐使用:SetAtGrow(int index,ARG_TYPE newElement ),它与Add相比,就是可以利用它修改数组中的数组;而如果用add,那么必须先RemoveAll l 获得元素个数和最大下标 GetSize():可以返回数组中元素的个数。 GetUpperBound():返回数组中的最大下标,一般加1就和GetSize()相等。 l 获得成员值 一般可以用GetAt(),有时可能要强制类型转化。如: CObArray array; Cline *pline=new Cline(100,100,200,200);//Cline为直线类,用起点和终点坐标初始化 array.Add(pline);//此处存储的只是一个地址 Cline *p=(Cline*)array.GetAt(0);//必须强制类型转换 注意这里必须使用new动态创建内存空间。如果是局部变量,等到函数结束,就不能够再通过数组来引用这块内存了,因为已经析构。 当然也可以不用类型转化。此时可以用集合类CTypedPtrArray,例如 CTypedPtrArray<CobArray,Cline*) array ;// 表示array是CobArray对象,专门存储Cline*指针 Cline *pline=new Cline(100,100,200,200);//Cline为直线类,用起点和终点坐标初始化 array.Add(pline); Cline *p=array.GetAt(0);//不用强制类型转换 l 修改成员值 一般可以使用函数SetAt(),但是在修改之前,这个元素的内存空间必须已经分配,比如下面这样写是错误的: CUIntArray Array; Array.SetAt(0,10) ;//想把第一项修改为10; 可以这样写来修改元素的值: CUIntArray Array; Array.Add(5) ; Array.SetAt(0,10) ;//把第一项5修改为10; 另外用数组成员引用符号[]来表示也可以来修改或者是获得元素值。 CUIntArray Array; Array.Add(5) ; Array[0]=5 ;//把第一项5修改为10; 同样 这样写是错误的: CUIntArray Array; Array.Add(5) ; Array.GetAt(0)=5 ;//想把第一项5修改为10; l 删除元素 RemoveAt():删除一个元素,删除后,数组中的索引号会自动改变。 RemoveAll():删除所有元素。 注意如果要同时删除几个元素,必须从后面删除起。 比如: CUIntArray Array; Array.Add(5) ; Array.Add(10); Array.Add(13); Array.RemoveAt(0); Array.RemoveAt(1); 本来是要删除第1个元素和第二个元素,但结果却是把第一个元素和第三个元素删除了,因为当调用Array.RemoveAt(0);删除第一个元素后,索引号开始变化,元素10成为索引要从1变为0,而元素13的索引号从2变为1。解决这个问题可以从后面开始删除: CUIntArray Array; Array.Add(5) ; Array.Add(10); Array.Add(13); Array.RemoveAt(1); Array.RemoveAt(0); 只是改变了顺序,效果却大不相同哦! (2) 链表 l 添加成员 Clist<int,int> m_intlist ; m_intlist.AddTail(36) ;//在尾部添加 m_intlist.AddHead(34) ;//在头部添加 l 遍历 POSITION pos=m_intlist.GetHeadPosition() ; While(pos !=NULL) { int i=m_intlist.GetNext(pos) ; … }//数组中有索引号,要方便一些。 其他用法数组差不多,不作介绍。 6. 动态创建的含义 举例说明: 还是有个直线类,现在要串行化保存。 l 添加元素 Cline *line =new Cline(100,100,200,200); m_array.Add(line); //CObArray m_array; 类中的成员变量 l 在文档类中保存和读取 Void CMyDocument::Serialize(CArchive & ar) { m_array.Serialize(ar); } 实际上在m_array.Serialize(ar);的内部实现用到了for循环,一个一个元素的存储和读取的。 前面已经说过line必须是动态分配空间的,所以存储是可以理解的。但是如果关闭这个程序,所有内存全部释放,此时再次运行程序,打开文件,肯定会调用m_array.Serialize(ar);,在内部又是采用for循环一个一个读取,但是这里并我并没有动态分配空间,它从磁盘读取的内容(Cline)到底存在哪里啊? 在深入浅出MFC中给出 了很好的说明。在调用CArchive中这个重载符号”>>”,也就是读取时,内部会再次调用一系列的函数,有一个是CreateObject(),它的代码就是 CObject *Cline ::CreateObject() { return new Cline; } 一切释然!你可能会问CreateObject这个函数在哪里定义的?没有显示定义啊!一切定义都在这2宏中:DECLARE_SERIAL和IMPLEMENT_SERIAL,更详细的内容请参考深入浅出MFC,一切秘密都在其中!!!

评论