




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
VisualC++与面向对象程序设计教程第三部分面向对象1、类和对象:数据和对应操作封装在一起2、继承和派生:3、多态性面向对象的思想面向过程的程序设计(StructureProgramming)以功能为中心,采用函数来描述(动词)面向对象程序设计(OOP)面向对象程序设计方法认为,客观世界是由各种各样的实体组成的,这些实体就是面向对象方法中的对象。消息是向某对象请求服务的一种表达方式对象之间的交互通过发送消息来实现。消息包括:目标对象,请求的方法,参数面向对象程序设计的特点四个基本特征:抽象(类)(数据抽象+代码抽象)封装(过程和数据封藏起来)继承(基类和派生类)多态性(虚函数、函数重载)OOP的优点开发时间短,效率高,可靠性高,所开发的程序更强壮重用,共享,可维护性,精简适合于大程序长时间的开发工作类与对象类的声明类的定义成员函数的定义数据成员的定义对象的引用对象作函数的参数对象作函数的返回值为什么要引入类工资单:姓名、单位、编号.....成绩单:姓名、学号、各科成绩.....简单数据单元无法将这样记录作为一个数据单位处理一一对应关系以工资单为例月份工号姓名工作部门工作时间基本工资2002.90002张三西安交大1990.7.11000校内津贴岗位津贴水电费房租实发工资200300501501300类的层次关系工作部门:字符串姓名:字符串职务:代码(0~99)int工作时间:年(xxxx):int月(1~12):char日(1~31):char家庭情况婚否:(0,1)int是否是双职工:int基本工资:double岗位津贴:double劳保福利:double独生子女:double房租:double电费:double水费:double取暖费:double保育费:double实发工资:double类(Class)----数据类型类是具有相同属性和相同的方法的对象的集合,它是一种既包含数据又包含函数的抽象数据类型。类是将一类对象和其他对象区别开来的一组描述。类是对象集合的抽象,对象是类的一个实例。类的种类 用struct关键字声明的类 用union关键字声明的类 用class关键字声明的类类的定义1.数据成员(DataMember),即类的属性;2.成员函数(MemberFunction),即类的方法;3.构造函数(constructor)和析构函数(destructor),这将在7.4节介绍;4.运算符函数,在第9章介绍。对象(Object)----数据对象是包含现实世界物体特征的抽象实体,反映了系统为之保存信息和(或)与之交互的能力。对象=数据+作用于这些数据上的操作
=属性(Attribute)+方法(Method)消息(Message)----函数调用消息是向某对象请求服务的一种表达方式。对象之间通过传递消息来实现相互的通信。类的定义
class<类名>
{
private:
//私有成员
<数据成员或成员函数表>;
public:
//公有成员
<数据成员或成员函数表>;
protected:
//保护成员
<数据成员或成员函数表>;
……};分析:编写简单的人事系统(子程序)人工作部门姓名出生日期职务工资基本工资岗位津贴……定义一个Person类,用来说明人员类对象//Example7-1:定义Person类classPerson{private: char m_strName[20]; int m_nAge; int m_nSex;public: void Register(char*name,intage,charsex); char* GetName(); int GetAge(); char GetSex(); void ShowMe();};成员函数的定义成员函数的一般形式:<类型><类名>::<函数名>(<参数表>){<函数体>}编写Person类成员函数的定义。//Example7-2:Person类成员函数的定义voidPerson::Register(char*name,intage,charsex){ strcpy(m_strName,name); m_nAge=age; m_nSex=(sex=='m'?0:1);}char*Person::GetName(){ returnm_strName;}intPerson::GetAge(){ returnm_nAge;}charPerson::GetSex(){ return(m_nSex==0?'m':'f');}voidPerson::ShowMe(){ cout<<GetName()<<'\t'<<GetAge()<<'\t'<<GetSex()<<endl;}对象的引用说明对象的一般形式(类的实例化):
<类名><对象1>,<对象2>,…对类成员的访问
.
运算符
->
运算符Person对象的引用成员函数访问同类中的数据成员(公有和私有)在对象外访问其数据成员或成员函数需使用运算符“.”访问对象的成员
禁止直接访问一个对象中的私有成员同类对象之间可以整体赋值对象用作函数的参数时属于赋值调用;函数可以返回一个对象。
例如:Personperson1,person2;
int
nage=person1.GetAge();person1=person2;Person*p;p=newPerson;nage=p->GetAge();完整的人事资料输入输出程序。//Example7-3:人事资料的输入和输出voidmain(){ charname[20],sex;intage;Personperson1,person2; cout<<"Enteraperson'sname,ageandsex:"; cin>>name>>age>>sex; person1.Register(name,age,sex); cout<<"person1:\t";person1.ShowMe(); person1.Register("Zhang3",19,'m'); cout<<"person1:\t";person1.ShowMe(); person2=person1; //对象之间的赋值
cout<<"person2:\t";person2.ShowMe();}多文件结构按照WINDOWS程序多文件的特点,将其改造成多文件结构通常将类的定义放在头文件中,成员函数的实现放在类对应的CPP文件中;然后通过#include的包含关系将多文件联系起来。内联成员函数classPerson{private: charm_strName[20]; intm_nAge;intm_nSex;public: void Register(char*name,intage,charsex) { strcpy(m_strName,name); m_nAge=age; m_nSex=(sex=='m'?0:1); } char* GetName() { returnm_strName; } int GetAge() { returnm_nAge; } charGetSex() { return(m_nSex==0?'m':'f');}};构造函数与析构函数构造函数(Constructor)定义了创建对象的方法,提供了初始化对象的一种简便手段。
与构造函数相对应,析构函数(Destructor)用于撤消一个对象。
构造函数(Constructor)格式:
<类名>(<参数表>);注意事项:构造函数必须与类名相同构造函数没有返回值其功能是对对象进行初始化,一般由一系列赋值语句构成由系统自动调用析构函数(Destructor)格式为:
<类名>::~<类名>();注意事项:函数名与类名相同,只是在前边加“~”符号析构函数不得返回任何值析构函数不得带有任何参数其功能是释放对象成员所占用的存储,一般由一系列的delete组成由系统自动调用为类Person增加构造函数和析构函数。classPerson{Private: charm_strName[20];int m_nAge; int m_nSex;public: person(constchar*name,intage,charsex)//构造函数
{strcpy(m_strName,name);m_nAge=age; m_nSex=(sex==’m’?0:1);}voidRegister(char*Name,intAge,charSex);void GetName(char*Name);intGetAge();charGetSex();};数据成员的初始化1.在构造函数的函数体中进行初始化。2.在构造函数的头部初始化。3.混合初始化。4.拷贝构造函数在构造函数的函数体中初始化classPerson{ char m_strName[20];intm_nAge;intm_nSex;public: Person(){strcpy(m_strName,”XXX”);m_nAge=0;m_nSex=0;} Person(char*name,intage,charsex) { strcpy(m_strName,name);m_nAge=age;m_nSex=(sex=='m'?0:1); }}例如,当遇到声明
Personpersonl(“Zhang3”,19,‘f’); Personperson2=Person(“Zhang3”,19,‘f’);在构造函数的头部初始化。其格式为:
<类名>::<构造函数>(<参数表>):<变量1>(<初值1>),…,<变量n>(<初值n>)
{ …… }例如Person::Person():m_nAge(0),m_nSex(0) { }混合初始化。例如Person::Person():m_nAge(0),m_nSex(0) { strcpy(m_strName,“XXX”); }拷贝构造函数拷贝构造函数是一种特殊的构造函数例如Person(Person&p){ strcpy(m_strName,p.GetName()); m_nAge=p.GetAge(); m_nSex=(p.GetSex()=='m'?0:1);}Personpersonl(“Zhang3”,19,‘f’);Personperson2=Person(“Zhang3”,19,‘f’);对象与指针指向对象的指针
类名*指针变量名表;
例: Personperson1(“Zhang3”,19,’f’); Person*ptr=&Person1; ptr->Speak();动态存储名字指针=new名字(名字初始化值);delete名字指针;例:Person*p=newPerson;deletep;this指针:指向该对象本身的指针MFC的CString类(#include<afx.h>)赋值/连接运算=、 +、+=比较运算<、<=、==、Compare、CompareNoCase截取运算Mid、Left、Right转换运算MakeUpper、MakeLower、MakeReverseCString类(续)查看字符信息
GetAt、GetLength、IsEmpty修改字符信息
SetAt、Insert、Delete格式化输出
FormatCString类举例#include<iostream.h>#include<afx.h>voidmain(){ CStrings; s="123456789"; cout<<s<<endl; s.MakeReverse(); cout<<s<<endl; s.Format("s=%d",100); cout<<s<<endl;}MFC的CTime类和CTimeSpan类构造函数
CTime、GetCurrentTime截取函数
GetYear、GetMonth、GetDay……转换函数
Format……运算符
=、+、-……CTime类举例#include<iostream.h>#include<afx.h>voidmain(){ CTimet; CStrings; t=CTime(1999,3,19,22,15,0); s=t.Format("%A,%B%d,%Y"); cout<<s<<endl; t=CTime::GetCurrentTime(); s=t.Format("%A,%B%d,%Y"); cout<<s<<endl;}CTimeSpan类构造函数CTimeSpan();CTimeSpan(constCTimeSpan&timeSpanSrc);CTimeSpan(LONGlDays,intnHours,intnMins,intnSecs);方法LONGGetDays(); //返回此CTimeSpan对象中的天数intGetHours(); //返回此CTimeSpan对象中的小时数intGetMinutes(); //返回此CTimeSpan对象中的分钟数CTime类和CTimeSpan类的运算= //赋一个新的时间值+,- //将CTime对象加上或减去一个CTimeSPan对象+=,-= //将CTime对象加上或减去一个CTimeSpan对象>,<,>=,<=,==,!= //比较两个CTime对象举例:CTimet1(2000,3,19,22,15,0);CTimet2(2000,3,20,22,15,0);CTimeSpants=t2-t1; //计算两日期的间隔t2+=CTimeSpan(1,0,0,0);//在某日期上加一间隔类的嵌套classEmployee{CString m_sDepartment; //工作部门
CString m_sName; //姓名
CTime m_tBirthdate; //出生日期
Position m_nPosition; //职务
CTime m_tDateOfWork; //参加工作时间
Salary m_Salary; //工资public:Employee(LPCTSTRlpszDepart,LPCTSTRlpszName,CTimetBirthdate,PositionnPosition,CTimetDateOfWork);//构造函数
......}继承和派生派生类的定义格式为:class派生类名:继承方式基类名1,继承方式基类名2,…,继承方式基类名n{
派生类增加的成员声明;};水果的分类
派生类的语法结构class<派生类名>:<访问权限><基类名>{private:新增私有数据成员和成员函数protected:新增保护数据成员和成员函效public:新增公有数据成员和成员函效}派生类中的变化
派生类对基类的扩充派生类对基类成员的改造
系统的默认值就是私有继承(private)。
派生类的继承方式私有继承private公有继承public
保护继承protected公有继承(public) 公有继承方式创建的派生类对基类各种成员访问权限如下:基类公有成员相当于派生类的公有成员,即派生类可以象访问自身公有成员一样访问从基类继承的公有成员。
基类保护成员相当于派生类的保护成员,即派生类可以象访问自身的保护成员一样,访问基类的保护成员。
对于基类的私有成员,派生类内部成员无法直接访问。派生类使用者也无法通过派生类对象直接访问。
实例:公有继承(public)
classPerson{private: char m_strName[20]; intm_nAge; int m_nSex; public: void GetName(char*Name); int GetAge(); charGetSex(); ......};classEmployee:publicPerson{charm_sDepartment[21];charm_sPosition[21];floatm_fSalary;public:Employee(){}voidSetDepartment(constchar*);voidSetSalary(float);char*GetPosition()const;floatGetSalary()const;......};从Person类公有派生一个职员类
classEmployee:publicPerson{ charm_strDept[20]; floatm_fSalary;public: Employee() {EmployeeRegister("XXX",0,'m',"XXX",0);} EmployeeRegister(char*name,intage,charsex,char*dept,floatsalary); voidShowMe();};私有继承
(private)派生类对基类各种成员访问权限如下:基类公有成员和保护成员都相当于派生类的私有成员,派生类只能通过自身的函数成员访问他们
对于基类的私有成员,无论派生类内部成员或派生类使用者都无法直接访问。
实例:私有继承(private)
classPerson{private: char m_strName[20]; intm_nAge; int m_nSex; public: void GetName(char*Name); int GetAge(); charGetSex(); ......};classEmployee:privatePerson{charm_sDepartment[21];charm_sPosition[21];floatm_fSalary;public:Employee(){}voidSetDepartment(constchar*);voidSetSalary(float);char*GetPosition()const;floatGetSalary()const;......};人员类(Person)的私有派生类classEmployee:privatePerson //雇员类定义{ charm_strDept[20]; //工作部门
floatm_fSalary; //月薪public: Employee() {EmployeeRegister("XXX",0,'m',"XXX",0);} EmployeeRegister(char*name,intage,charsex,char*dept,floatsalary); voidShowMe(); //显示雇员信息
char*GetEmployeeName() {return GetName();}//取姓名
charGetEmployeeSex() {return GetSex();}//取性别
intGetEmployeeAge() {return GetAge();}//取年龄};保护继承(public) 保护继承方式创建的派生类对基类各种成员访问权限如下:基类的公有成员和保护成员都相当于派生类的保护成员,派生类可以通过自身的成员函数或其子类的成员函数访问他们对于基类的私有成员,无论派生类内部成员或派生类使用者都无法直接访问派生类的构造函数和析构函数派生类构造函数的一般形式为: 派生类名::派生类名(参数总表):基类名1(参数表1),…,基类名n(参数表n), 内嵌对象名1(对象参数表1),…,内嵌对象名m(对象参数表m)
{
派生类新增加成员的初始化;
}派生类与基类的析构函数没有什么联系,彼此独立,派生类或基类的析构函数只作各自类对象消亡前的善后工作
派生类构造函数和析构函数的执行
classPerson{ char m_strName[10]; int m_nAge;public: Person(char*name,intage) { strcpy(m_strName,name); m_nAge=age; cout<<"constructorofperson"<<m_strName<<endl; } ~Person() {cout<<"deconstrutorofperson"<<m_strName<<endl;}};派生类构造函数和析构函数的执行classEmployee:publicPerson{ char m_strDept[20]; PersonWang;public: Employee(char*name,intage,char*dept,char*name1,intage1) :Person(name,age),Wang(name1,age1) { strcpy(m_strDept,dept); cout<<"constructorofEmployee"<<endl; } ~Employee(){cout<<"deconstrucorofEmployee"<<endl;}};派生类构造函数的执行次序首先,调用基类构造函数,调用顺序按照它们被继承时声明的基类名顺序执行。其次,调用内嵌对象构造函数,调用次序按各个对象在派生类内声明的顺序。最后,执行派生类构造函数体中的内容。析构函数派生类析构函数执行过程恰与构造函数执行过程相反。首先执行派生类析构函数然后执行内嵌对象的析构函数最后执行基类析构函数类模版
template<class<类型参数>> class<类名> { …… };多态性含义实现“一种接口,多种方法”的技术某类的对象在接受同样的消息时,做出不同的响应多态性的形式编译时多态性
编译器对源程序进行编译时就可以确定所调用的是哪一个函数,编译时多态性通过重载来实现;函数重载运算符重载运行时多态性
在程序运行过程中根据具体情况来确定调用的是哪一个函数;虚函数编译时多态性——函数重载(兔子逃生)class兔子{public:
……void逃生(老鹰a){“兔子蹬鹰”;}void逃生(狼
b){“动如脱兔”;}……};
运行时多态性——虚函数(catordog???)class宠物{public:voidchar*speak(){cout<<"zzz";};
…};class猫:public宠物{public:voidchar*speak(){cout<<"miao!miao!";}
…};class狗:public宠物{public:voidchar*speak(){cout<<"wang!wang!";}
…};例:catordog???(续)voidmain(){ ……
宠物*p;//p为宠物类指针
猫
cat1; //定义猫类对象
狗
dog1; //定义狗类对象……根据用户输入将猫或狗对象地址赋给p指针,例如用户输入1,则执行p=&cat1;用户输入2,则执行p=&dog1;……p->speak();
……}
派生类对象替换基类对象
原则:凡是基类对象出现的场合都可以用公有派生类对象取代
形式
(1)派生类对象给基类对象赋值(2)派生类对象可以初始化基类对象的引用(3)可以令基类对象的指针指向派生类对象,即将派生类对象的地址传递给基类指针
例:派生类对象替换基类对象
#include<iostream.h>classPet //基类{public: voidSpeak() {cout<<"Howdoesapetspeak?"<<endl;}};classCat:publicPet //派生类{public: voidSpeak() {cout<<"miao!miao!"<<endl;}};例:派生类对象替换基类对象(续一)classDog:publicPet //派生类{public: voidSpeak() {cout<<"wang!wang!"<<endl;}};voidmain(){ Pet *p1,*p2,*p3,obj; //基类对象指针p1,基类对象obj Dogdog1; Catcat1; obj=dog1; //用Dog类对象给Pet类对象赋值
obj.Speak(); 派生类对象替换基类对象(续二)
p1=&cat1; //用Cat类对象地址给基类指针赋值
p1->Speak(); p1=&dog1; //用Dog类对象地址给基类指针赋值
p1->Speak(); p2=newCat; //动态生成Cat类对象
p2->Speak(); p3=newDog; //动态生成Dog类对象
p3->Speak(); Pet &p4=cat1; //以Cat类对象初始化Pet类引用
p4.Speak();}
虚函数
定义:在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数
语法:virtual函数返回类型
函数名(参数表){
函数体}用途:实现多态性,通过指向派生类的基类指针,访问派生类中同名覆盖成员函数,
虚函数实现多态性#include<iostream.h>classPet //基类{public:
virtualvoidSpeak() {cout<<"Howdoesapetspeak?"<<endl;}};classCat:publicPet //派生类
{public:
virtualvoidSpeak() {cout<<"miao!miao!"<<endl;}};虚函数的使用限制应通过指针或引用调用虚函数,而不要以对象名调用虚函数说明语句在派生类中重定义的基类虚函数仍为虚函数,同时可以省略virtual关键字
不能定义虚构造函数,可以定义虚析构函数
抽象类纯虚函数
virtual返回类型
函数名(参数表)=0
纯虚函数是为了实现多态性而存在,具体实现只能在派生类中完成。抽象类
至少包含一个纯虚函数的类称为抽象类
抽象类为其所有子类提供了统一的操作界面,使其派生类具有一系列统一的方法。
抽象类的使用要求
抽象类不能实例化抽象类只作为基类被继承可以定义指向抽象类的指针或引用
抽象宠物类的实现#include<iostream.h>#include<string.h>classPet //基类{ char m_strName[20]; int m_nAge; char m_strColor[12];public: char m_strType[10]; Pet(char*,int,char*); char*GetName() {returnm_strName;} int GetAge() {returnm_nAge;} char*GetColor() {returnm_strColor;} virtualvoidSpeak()=0; virtualvoidGetInfo(){}};抽象宠物类的实现(续1)Pet::Pet(char*name,intage,char*color){ strcpy(m_strName,name); m_nAge=age; strcpy(m_strColor,color); strcpy(m_strType,"pet");}抽象宠物类的实现(续2)classCat:publicPet //派生类
{public: Cat(char*name,intage,char*color):Pet(name,age,color){} voidSpeak() {cout<<"Soundofspeak:miao!miao!"<<endl<<endl;} voidGetInfo();};voidCat::GetInfo(){ cout<<"Thecat'sname:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 物流行业信息安全保障措施
- 二零二五年度房屋租赁合同书:针对企业办公空间的模板
- 二零二五年度国际会议外籍嘉宾聘用协议
- 二零二五年度民宿合作社民宿与旅游规划机构合作协议
- 二零二五年度一手房居间代理买卖合同范本
- 二零二五年度窗帘品牌授权与区域代理合作协议
- 2025至2030年中国组合槽刀数据监测研究报告
- 二零二五年度农产品期货交易风险管理合同
- 二零二五年度人工智能技术研发聘用劳动合同
- 二零二五年度房屋抵押贷款与社区文化活动赞助合同
- 产后疼痛管理指南
- 2025年安徽马鞍山市两山绿色生态环境建设有限公司招聘笔试参考题库附带答案详解
- 工娱治疗及其护理
- 人效管理措施
- 2024-2025学年人教部编版七年级上语文寒假作业(五)
- 四年级下册劳动《小小快递站》课件
- 中国妊娠期糖尿病母儿共同管理指南(2024版)解读
- 篮球教练职业生涯规划
- 《学生档案信息管理系统的开发》6500字(论文)
- 春节促销活动方案(7篇)
- 《股市的基础常识》课件
评论
0/150
提交评论