C++语言程序设计项目实践(清华大学计算机基础教育课程系列教材)
作者简介
内容简介
第5章数据结构设计与实现
数据结构设计与实现
本章主要描述ContactList系统的总体数据结构设计与实现方法。数据结构设计应当遵循《需求说明书》和《概要设计说明书》的要求。由于ContactList系统使用了面向对象的思想,所以数据结构设计应当遵循面向对象的三大特性(抽象、封装和继承)。综上所述,本系统的数据结构的主要设计方法是定义相关类,在类中定义所需的数据成员和函数成员(部分自定义数据类继承了MFC系统提供的数据类)。
5.1CPerson类的设计与实现
在ContactList项目中,CPerson类主要描述一个联系人的信息,包括姓名、性别、手机号、QQ号和组编号,对每个属性属性都提供了Get/Set函数、基础数据存储以及其他函数的操作功能。ContactList项目的总体结构设计如图51所示。
图51总体结构设计图
5.2添加CPerson类
(1) 单击左下角的Class View切换到类视图,如图52所示。
图52类视图
(2) 在类视图中的ContactList上右击右击,在弹出的快捷菜单中选择Add→Class命令,如图53所示。
图53选择Class命令
(3) 弹出类向导对话框,选择C++ Class后单击Add按钮,如图54所示。
图54添加类
(4) 在类向导对话框中输入相应内容,如图55所示。
图55添加类命名
Class name: 表示添加类的名称。
.h file: 表示该类添加后生成的头文件,主要存放成员数据的声明。
.cpp file: 表示该类添加后生成的源文件源文件,主要存放成员数据的定义。
(5) 单击Finish按钮。
5.3添加CPerson类的成员变量
(1) CPerson类的成员变量设置如表51所示。
(2) 单击Class View切换到类视图。
(3) 双击双击CPerson类打开该类的Person.h头文件。表51CPerson类的成员变量
成员描述m_strName姓名: 描述一个名字,20个字符以内m_bMale性别: TRUE表示男;FALSE表示女m_strPhoneNo手机号: 11位数字m_strQQNoQQ号: 10位以内的数字m_iGroupNo组号: 全局字符串数组g_lstGroups的索引(4) 在Person.h文件中添加如下成员变量代码,然后保存,如图56所示。protected:
CStringm_strName;//姓名: 20个字符以内
BOOL m_bMale; //性别: TRUE表示男;FALSE表示女
CString m_strPhoneNo; //手机号: 11位数字
CString m_strQQNo; //QQ号: 10位以内的数字
int m_iGroupNo; //组号: 全局字符串数组g_lstGroups的索引
图56CPerson成员变量
5.4添加CPerson类的成员函数
CPerson类的成员函数设置如表52所示。表52CPerson类的成员函数
续表成员 描述CPerson~CPerson默认构造构造函数和虚析构析构函数,这是由App Wizard自动创建的初始函数体。重载重载的构造函数用于成员变量初始化GetName/SetName获取/设置名字IsMale/SetMale判断/设置性别GetPhoneNo/SetPhoneNo获取/设置手机号码GetQQNo/SetQQNo获取/设置QQ号码GetGroupNo/SetGroupNo获取/设置分组类型打开Person.h文件,添加如下自定义内联成员函数代码,然后保存,如图57所示。public:
CStringGetName(){ return m_strName; }
BOOL IsMale() { return m_bMale; }
CString GetPhoneNo() { return m_strPhoneNo; }
CString GetQQNo() { return m_strQQNo; }
int GetGroupNo() { return m_iGroupNo; }
void SetName(CString strName) { m_strName=strName; }
void SetMale(BOOL bMale) { m_bMale=bMale; }
void SetPhoneNo(CString strPhoneNo) { m_strPhoneNo=strPhoneNo; }
void SetQQNo(CString strQQNo) { m_strQQNo=strQQNo; }
void SetGroupNo(int iGroupNo) { m_iGroupNo=iGroupNo; }
图57CPerson成员函数
5.5重载CPerson类的构造函数
重载是函数多用性的一个表现,C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,也就是用同一个函数实现功能类似但所处理数据类型不同的问题。本节重载CPerson类构造函数,使CPerson对象带默认参数值,即为后添加联系人功能的默认值。
(1) 在Person.h文件的CPerson类中添加下面的代码,如图58所示。CPerson(CString strName, BOOL bMale=TRUE, CString strPhoneNo=_T(\"88888888888\"),
CString strQQNo=_T(\"0000\"), int iGroupNo=0);
图58重载CPerson类的构造函数声明
(2) 单击Solution Explorer切换到解决方案视图。
(3) 双击Person.cpp打开该文件,在相应的位置添加如下代码,如图59所示。CPerson::CPerson(CString strName, BOOL bMale, CString strPhoneNo, CString strQQNo,
int iGroupNo)
: m_strName(strName), m_bMale(bMale), m_strPhoneNo(strPhoneNo),
m_strQQNo(strQQNo), m_iGroupNo(iGroupNo)
{
}//end of CPerson::CPerson()
图59重载CPerson类的构造函数定义
5.6CPerson成员变量的初始化
打开Person.cpp文件,在默认构造函数CPerson::CPerson(void)中添加如下代码,如图510所示。 m_strName=_T(\"Unknown\");
m_bMale=TRUE;
m_strPhoneNo=_T(\"88888888888\");
m_strQQNo=_T(\"00000\");
图510初始化CPerson成员变量
5.7CPersonList类的设计与实现
CPersonList记录整个通讯录对象,是元素类型为CPerson的动态数组,需要先用类型定义关键字 typedef 定义一个元素为CPerson的CArray类CPersons,再将CPersonList定义成CPersons的派生类(从而也是CArray的派生类),如图511所示。
图511CPerson的动态数组
5.8类模板和动态数组CArray
数组是在编码过程中经常用到的集合命名,它把具有相同类型的若干元素按无序的形式组织起来。普通数组使用起来很麻烦,在程序变化的过程中数组一般不是固定的,而是动态变化的,就像通讯录项目中联系人的数量一样,不同的使用者联系人的数量是不一样的,并且随着时间的发展联系人的数量也会有所改变,所以本项目为了解决联系人存储的问题,引入MFC中几个常用的类模板,其中用得最多的是CArray。
CArray是MFC中非常重要的类模板之一,使用类模板可以使用户为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能取任意类型。类模板是对一批仅成员数据类型不同的类的抽象,程序员只要为这批类组成的整个类家族创建一个类模板,给出一套程序代码,就可以用来生成多种具体的类,从而大大提高编程效率。定义类模板的一般形式如下。 template <类型名 参数名1,类型名参数名2,…>
class 类名
{
类声明体
};
本项目将通过CArray动态数组管理联系人的增/删/查/改,以提高对联系人的管理效率。CArray的原型声明如下。 template