
第4章C程序设计教程与实验指导杨国兴类与对象学习教案.ppt
65页会计学1第第4章章C程序设计教程程序设计教程(jiàochéng)与实验与实验指导杨国兴类与对象指导杨国兴类与对象第一页,共65页第第4章章 类与对象类与对象(duìxiàng)4.1 类与对象4.2 构造函数与析构函数4.3 类的组合(zǔhé)4.4 友元4.5 静态成员4.6 对象数组与对象指针4.7 this指针第1页/共64页第二页,共65页4.1 4.1 类与对象类与对象(duìxiàng)(duìxiàng)4.1.1 类与对象的概念 对象(object):是现实世界中的客观事物 类(class):是把具有相同属性的事物划分(huà fēn)为一类,从而得出的抽象概念 面向对象程序设计中的类,是具有相同属性和服务的一组对象的集合,它为属于该类的全部对象提供了抽象的描述 对象是类的实例,类是同种对象的抽象第4章 类与对象(duìxiàng) 如:如:如:如:确定大小和颜色的矩形都是一个个确定大小和颜色的矩形都是一个个确定大小和颜色的矩形都是一个个确定大小和颜色的矩形都是一个个具体的对象具体的对象具体的对象具体的对象,而将所有矩形的共同特点抽象,而将所有矩形的共同特点抽象,而将所有矩形的共同特点抽象,而将所有矩形的共同特点抽象出来,就是一个出来,就是一个出来,就是一个出来,就是一个矩形类矩形类矩形类矩形类。
这些共有的属性包括这些共有的属性包括这些共有的属性包括这些共有的属性包括颜色颜色颜色颜色 ( color )( color ),,,,左上角坐标左上角坐标左上角坐标左上角坐标 ( left, top )( left, top ),,,,长长长长 ( length )( length )和和和和宽宽宽宽 ( width ( width ) ) 等;等;等;等; 对这些属性的处理包括对这些属性的处理包括对这些属性的处理包括对这些属性的处理包括改变矩形的颜色改变矩形的颜色改变矩形的颜色改变矩形的颜色 ( SetColor ) ( SetColor ) 和和和和大小大小大小大小 ( SetSize ) ( SetSize ) ,,,,移动矩移动矩移动矩移动矩形到新的位置形到新的位置形到新的位置形到新的位置 ( Move )( Move ),,,,绘出矩形绘出矩形绘出矩形绘出矩形 ( Draw ) ( Draw ) 等将矩形的这些属性和方法作为一个整体,等将矩形的这些属性和方法作为一个整体,等将矩形的这些属性和方法作为一个整体,等。
将矩形的这些属性和方法作为一个整体,封装在一起形成一个矩形类封装在一起形成一个矩形类封装在一起形成一个矩形类封装在一起形成一个矩形类第2页/共64页第三页,共65页4.1 4.1 类与对象类与对象(duìxiàng)(duìxiàng)4.1.2 类的声明 class 类名 { private: 私有数据(shùjù)成员和成员函数; protected: 保护数据(shùjù)成员和成员函数; public: 公有数据(shùjù)成员和成员函数; };第4章 类与对象(duìxiàng)第3页/共64页第四页,共65页例例例例4.1 4.1 定义定义定义定义(dìngyì)(dìngyì)一个长方形类一个长方形类一个长方形类一个长方形类CRectCRect,其数据成员包括颜色,左,其数据成员包括颜色,左,其数据成员包括颜色,左,其数据成员包括颜色,左上角坐标,长和宽,其函数成员包括改变矩形的颜色上角坐标,长和宽,其函数成员包括改变矩形的颜色上角坐标,长和宽,其函数成员包括改变矩形的颜色上角坐标,长和宽,其函数成员包括改变矩形的颜色(SetColor)(SetColor)和和和和大小(大小(大小(大小(SetSizeSetSize),移动矩形到新的位置(),移动矩形到新的位置(),移动矩形到新的位置(),移动矩形到新的位置(MoveMove),绘出矩形),绘出矩形),绘出矩形),绘出矩形((((DrawDraw)。
class CRectclass CRect{ {private:private:char color[10];char color[10];int left;int left;int top;int top;int length;int length;int width;int width;public:public:void SetColor(char *c);void SetColor(char *c);void SetSize(int l, int w);void SetSize(int l, int w);void Move(int t,int l);void Move(int t,int l);void Draw();void Draw();}; }; 第4章 类与对象(duìxiàng)第4页/共64页第五页,共65页例例例例4.1 4.1 (续一)(续一)(续一)(续一) void CRect::SetColor(char *c)void CRect::SetColor(char *c){ {strcpy(color, c);strcpy(color, c);} }void CRect::SetSize(int l, int w)void CRect::SetSize(int l, int w){ {length=l;length=l;width = w;width = w;} }void CRect::Move(int t,int l)void CRect::Move(int t,int l){ {top = t;top = t;left = l;left = l;} }void CRect::Draw()void CRect::Draw(){ {cout << "cout << "矩形矩形(j (jǔ ǔxíng)xíng)左上角坐标为左上角坐标为(" << left << "," << top << ")" << endl;(" << left << "," << top << ")" << endl;cout << "cout << "矩形矩形(j (jǔ ǔxíng)xíng)长和宽分别为长和宽分别为" << length << "," << width << endl;" << length << "," << width << endl;cout << "cout << "矩形矩形(j (jǔ ǔxíng)xíng)的颜色是的颜色是" << color << endl;" << color << endl;} } 第4章 类与对象(duìxiàng)域运算符(域运算符(::)用于指出)用于指出(zhǐ chū)该函数是哪一个类的成员函数,用该函数是哪一个类的成员函数,用法:法: 类名类名::函数名(参数表)函数名(参数表)第5页/共64页第六页,共65页。
例例例例4.1 4.1 (续二)(续二)(续二)(续二) void main()void main(){ {CRect r; CRect r; r.SetColor("Red");r.SetColor("Red");r.Move(10,20);r.Move(10,20);r.SetSize(100,200);r.SetSize(100,200);();();r.Move(50,50);r.Move(50,50);r.SetColor("Blue");r.SetColor("Blue");();();} } 第4章 类与对象(duìxiàng)定义定义(dìngyì)CRect类的对象,定义类的对象,定义(dìngyì)对象的格式:对象的格式: 类名类名 对象名对象名1,对象名,对象名2,,……访问对象的公有成员访问对象的公有成员(chéngyuán),格式为:,格式为: 对象名对象名.公有成员公有成员(chéngyuán)函数名(参数表)函数名(参数表) 对象名对象名.公有数据成员公有数据成员(chéngyuán)名名程序运行结果为:程序运行结果为:矩形左上角坐标为(矩形左上角坐标为(2020,,1010))矩形长和宽分别为矩形长和宽分别为100100,,200200矩形的颜色是矩形的颜色是RedRed矩形左上角坐标为(矩形左上角坐标为(5050,,5050))矩形长和宽分别为矩形长和宽分别为100100,,200200矩形的颜色是矩形的颜色是BlueBlue 第6页/共64页第七页,共65页。
4.1 4.1 类与对象类与对象(duìxiàng)(duìxiàng)4.1.3 成员的访问控制 private: 私有访问权限,只允许类中的成员函数访问,其他函数不能访问 protected: 保护访问权限,在第7章中介绍 public: 公有访问权限,在任何函数中都可以(kěyǐ)访问 例:若主函数中有以下语句,是否正确? CRect r; strcpy( , “red”); = 10; = 20;第4章 类与对象(duìxiàng)在主函数中不能访问类的私有成员在主函数中不能访问类的私有成员第7页/共64页第八页,共65页4.1 4.1 类与对象类与对象(duìxiàng)(duìxiàng)4.1.3 成员的访问控制(续) 若不指定类中的成员的访问权限,则默认为私有成员 类也可以由struct关键字声明,strust与class的区别是:如果不指定访问权限,前者缺省的访问权限是公有的,而后者是私有的。
用struct声明前面(qián mian)的矩形类:struct CRect{void SetColor(char *c);void SetSize(int l, int w);void Move(int t,int l);void Draw();private:char color[10];int left;int top;int length;int width;};第4章 类与对象(duìxiàng)第8页/共64页第九页,共65页4.1 4.1 类与对象类与对象(duìxiàng)(duìxiàng)4.1.4 类的成员函数 1. 类成员函数的定义(dìngyì)方式在类外部定义(dìngyì):如前面定义(dìngyì)的长方形类的成员函数 一般格式为: 函数类型 类名::成员函数名(参数说明) { 函数体 } 在类中定义(dìngyì):如 class CRect {…… public:void setcolor( char *c ){ strcpy( color , c ); } …… };第4章 类与对象(duìxiàng)第9页/共64页第十页,共65页。
4.1 4.1 类与对象类与对象(duìxiàng)(duìxiàng)4.1.4 类的成员(chéngyuán)函数(续一) 2. 内联成员(chéngyuán)函数 将成员(chéngyuán)函数的定义直接写在类中即成为内联成员(chéngyuán)函数在类外定义时用inline指出: 如: inline void CRect::SetColor(char *c) {strcpy(color, c); } 第4章 类与对象(duìxiàng)第10页/共64页第十一页,共65页4.1 4.1 类与对象类与对象(duìxiàng)(duìxiàng)4.1.4 类的成员函数(续二) 3. 带默认参数值的成员函数 注意:默认参数只能在声明或定义中的一处给出,即如在类中的函数声明已经给出默认参数值:void SetSize(int l=100, int w=100);则在函数定义时就不能再给出默认值同样(tóngyàng)如果在定义时给出了默认值: void CRect::SetSize(int l=100, int w=100) { length=l; width = w; }在声明处就不能再给默认值了。
第4章 类与对象(duìxiàng) 返 回第11页/共64页第十二页,共65页4.2 4.2 构造函数构造函数(hánshù)(hánshù)与析构与析构函数函数(hánshù)(hánshù)构造函数:对对象进行构造函数:对对象进行(jìnxíng)(jìnxíng)初始化析构函数:在对象销毁时进行析构函数:在对象销毁时进行(jìnxíng)(jìnxíng)内存释放等清理工作内存释放等清理工作 4.2.1 4.2.1 构造函数构造函数 1. 1. 构造函数的特点构造函数的特点 (1) (1) 构造函数的函数名与类名相同构造函数的函数名与类名相同 (2) (2) 不能定义构造函数的类型(即不能指明构造函数返回值的类型)不能定义构造函数的类型(即不能指明构造函数返回值的类型) (3) (3) 构造函数应声明为公有函数构造函数应声明为公有函数 (4) (4) 构造函数不能在程序中调用,在对象创建时,构造函数被系统自动调构造函数不能在程序中调用,在对象创建时,构造函数被系统自动调用。
用 2. 2. 构造函数的作用构造函数的作用 构造函数的作用就是在对象被创建时利用特定的值构造对象,将对象初始构造函数的作用就是在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态,使此对象具有区别于其它对象的特征化为一个特定的状态,使此对象具有区别于其它对象的特征 第4章 类与对象(duìxiàng)第12页/共64页第十三页,共65页例例 为为CRect类添加类添加(tiān jiā)构造函数构造函数class CRectclass CRect{ {private:private:char color[10];char color[10]; …… ……public:public:CRect( );CRect( );CRect(char *c, int t, int left, int len, int wid);CRect(char *c, int t, int left, int len, int wid);void SetColor(char *c);void SetColor(char *c); …… ……}; }; CRect::CRect()CRect::CRect(){ {strcpy(color, "Black");strcpy(color, "Black");top = 0;top = 0;left = 0;left = 0;length = 0;length = 0;width = 0;width = 0;} } 二者是重载函数,在定义对象时,二者是重载函数,在定义对象时,如果不给出参数,就自动调用第一如果不给出参数,就自动调用第一个构造函数,如果给定个构造函数,如果给定5个参数就自个参数就自动调用第二个构造函数。
动调用第二个构造函数 第4章 类与对象(duìxiàng)第13页/共64页第十四页,共65页例例 为为CRect类添加类添加(tiān jiā)构造函数(续)构造函数(续)CRect::CRect(char *c, int t, int lef, int len, int wid )CRect::CRect(char *c, int t, int lef, int len, int wid ){ {strcpy(color, c);strcpy(color, c);top = t;top = t;left = lef;left = lef;length = len;length = len;width = wid;width = wid;} } void main()void main(){ {CRect r1; //CRect r1; //自动自动(zìdòng)(zìdòng)调用第一个构造函数调用第一个构造函数 CRect r2(“red”, 10,10,100,100); // CRect r2(“red”, 10,10,100,100); //自动自动(zìdòng)(zìdòng)调用第二个构造函数调用第二个构造函数CRect r3("green", 200,200,50,50); //CRect r3("green", 200,200,50,50); //自动自动(zìdòng)(zìdòng)调用第二个构造函数调用第二个构造函数r1.Draw();r1.Draw();r2.Draw();r2.Draw();r3.Draw();r3.Draw();} } 第4章 类与对象(duìxiàng)第14页/共64页第十五页,共65页。
例例4.2 构造函数的初始化表构造函数的初始化表#include
4.2 4.2 构造函数构造函数(hánshù)(hánshù)与析与析构函数构函数(hánshù)(hánshù)4.2.2 析构函数 1. 析构函数的特点 (1) 析构函数名字为符号“~”加类名 (2) 析构函数没有参数,不能指定返回值类型 (3) 一个类中只能定义一个析构函数,所以析构函数不能重载 (4) 当一个对象作用域结束时,系统自动调用析构函数 如CRect类的析构函数声明为:~CRect(); 定义为: CRect::~CRect() { …… } 2. 析构函数的作用 在删除一个对象前被调用,释放该对象成员(chéngyuán)的内存空间,以及其它一些清理工作 第4章 类与对象(duìxiàng)第16页/共64页第十七页,共65页例例例例4.3 4.3 设计一个简单的字符串类,类中有两个数据成员设计一个简单的字符串类,类中有两个数据成员设计一个简单的字符串类,类中有两个数据成员设计一个简单的字符串类,类中有两个数据成员(chéngyuán)(chéngyuán),分别表示字符串的长度和字符串的内容,有一个构造函数和一个,分别表示字符串的长度和字符串的内容,有一个构造函数和一个,分别表示字符串的长度和字符串的内容,有一个构造函数和一个,分别表示字符串的长度和字符串的内容,有一个构造函数和一个析构函数,函数析构函数,函数析构函数,函数析构函数,函数GetLength( )GetLength( )返回字符串长度,函数返回字符串长度,函数返回字符串长度,函数返回字符串长度,函数GetContents( )GetContents( )获获获获得字符串的内容,重载函数得字符串的内容,重载函数得字符串的内容,重载函数得字符串的内容,重载函数SetContents( )SetContents( )给字符串设置值。
给字符串设置值给字符串设置值给字符串设置值include
例例例例4.3 4.3 (续一)(续一)(续一)(续一)CString::CString()CString::CString(){ {length = 0;length = 0;contents = NULL;contents = NULL; cout << "cout << "字符串对象字符串对象字符串对象字符串对象(duìxiàng)(duìxiàng)初始化初始化初始化初始化" << endl;" << endl;} } CString::~CString()CString::~CString(){ { cout << contents << "cout << contents << "被销毁被销毁被销毁被销毁" << endl;" << endl;if(contents != NULL)if(contents != NULL)delete contents;delete contents;} }int CString::GetLength()int CString::GetLength(){ {return length;return length;} }void CString::GetContents(char *str)void CString::GetContents(char *str){ {strcpy(str, contents);strcpy(str, contents);} }第4章 类与对象(duìxiàng)第18页/共64页第十九页,共65页。
例例例例4.3 4.3 (续二)(续二)(续二)(续二)void CString::SetContents(int len, char *cont)void CString::SetContents(int len, char *cont){ {length = len;length = len;if(contents != NULL)if(contents != NULL)delete contents;delete contents;contents = new char[len+1];contents = new char[len+1];strcpy(contents,cont);strcpy(contents,cont);cout << "cout << "两个参数的两个参数的两个参数的两个参数的SetContentsSetContents函数函数函数函数(hánshù)" << endl;(hánshù)" << endl;} }void CString::SetContents( char *cont)void CString::SetContents( char *cont){ {length = strlen(cont);length = strlen(cont);if(contents != NULL)if(contents != NULL)delete contents;delete contents;contents = new char[length+1];contents = new char[length+1];strcpy(contents,cont);strcpy(contents,cont);cout << "cout << "一个参数的一个参数的一个参数的一个参数的SetContentsSetContents函数函数函数函数(hánshù)" << endl;(hánshù)" << endl;} } 第4章 类与对象(duìxiàng)重载函数重载函数SetContents( )都是将要设置的字符串长度赋给数据成员都是将要设置的字符串长度赋给数据成员 length,然后判断原来数据成员,然后判断原来数据成员 contents是否已经有数据(即已经不为空是否已经有数据(即已经不为空 NULL了),如果已不为空,则先释放原来的内存,再根据新字符串的长度重新申请内存。
了),如果已不为空,则先释放原来的内存,再根据新字符串的长度重新申请内存 第19页/共64页第二十页,共65页例例例例4.3 4.3 (续三)(续三)(续三)(续三)void main()void main(){ {CString str1,str2; //CString str1,str2; //两次调用构造函数两次调用构造函数两次调用构造函数两次调用构造函数 str1.SetContents("str1.SetContents("第一个第一个第一个第一个(yī (yī ɡ ɡè)è)字符串字符串字符串字符串"); //"); //调用有一个调用有一个调用有一个调用有一个(yī (yī ɡ ɡè)è)参数的参数的参数的参数的SetContentsSetContents函函函函数数数数 str2.SetContents(20, "str2.SetContents(20, "第二个字符串两个参数第二个字符串两个参数第二个字符串两个参数第二个字符串两个参数"); //"); //调用有两个参数的调用有两个参数的调用有两个参数的调用有两个参数的SetContentsSetContents函数函数函数函数 int i = str1.GetLength(); int i = str1.GetLength();char string[100]; char string[100]; str1.GetContents(string);str1.GetContents(string); cout << i << " "<< string << endl;cout << i << " "<< string << endl; i = str2.GetLength(); i = str2.GetLength();str2.GetContents(string);str2.GetContents(string); cout << i << " " << string << endl;cout << i << " " << string << endl;} } 第4章 类与对象(duìxiàng)程序运行结果为:程序运行结果为:字符串对象初始化字符串对象初始化字符串对象初始化字符串对象初始化一个参数一个参数(cānshù)(cānshù)的的SetContentsSetContents函数函数两个参数两个参数(cānshù)(cānshù)的的SetContentsSetContents函数函数12 12 第一个字符串第一个字符串20 20 第二个字符串两个参数第二个字符串两个参数(cānshù)(cānshù)第二个字符串两个参数第二个字符串两个参数(cānshù)(cānshù)被销毁被销毁第一个字符串被销毁第一个字符串被销毁 第20页/共64页第二十一页,共65页。
4.2 4.2 构造函数构造函数(hánshù)(hánshù)与析与析构函数构函数(hánshù)(hánshù)4.2.3 拷贝构造函数 拷贝构造函数也是构造函数,它的作用是用一个已经存在的对象初始化新对象,拷贝构造函数的参数为该类对象的引用 例 设计一个复数类,两个数据(shùjù)成员分别表示复数的实部(real)和虚部(imag),三个构造函数分别在不同的情况下初始化对象,函数Set()设置复数实部和虚部的值,函数Print()输出复数,函数Add()和函数Sub()分别实现复数的加减法运算第4章 类与对象(duìxiàng)第21页/共64页第二十二页,共65页例例例例4.4 4.4 源程序源程序源程序源程序#include "iostream“#include "iostream“using namespace std;using namespace std;class CComplex class CComplex { {private:private:double real;double real;double imag;double imag;public:public:CComplex();CComplex();CComplex(double r, double i);CComplex(double r, double i);CComplex(CComplex &c); //CComplex(CComplex &c); //复数类的拷贝复数类的拷贝复数类的拷贝复数类的拷贝(k(kǎ ǎobèi)obèi)构造函数声明构造函数声明构造函数声明构造函数声明void Set(double r, double i);void Set(double r, double i);void Print();void Print();CComplex Add(CComplex c);CComplex Add(CComplex c);CComplex Sub(CComplex c);CComplex Sub(CComplex c);}; }; 第4章 类与对象(duìxiàng)第22页/共64页第二十三页,共65页。
例例例例4.4 4.4 源程序(续一)源程序(续一)源程序(续一)源程序(续一)CComplex::CComplex()CComplex::CComplex(){ {real = 0.0;real = 0.0;imag = 0.0;imag = 0.0;} }CComplex::CComplex (double r, double i)CComplex::CComplex (double r, double i){ { real = r;real = r;imag = i;imag = i;} }CComplex::CComplex (CComplex &c) //CComplex::CComplex (CComplex &c) //复数类的拷贝构造函数定义复数类的拷贝构造函数定义复数类的拷贝构造函数定义复数类的拷贝构造函数定义(dìngyì)(dìngyì){ {real = ;real = ;imag = ;imag = ;} }// // 设置复数类的实部和虚部设置复数类的实部和虚部设置复数类的实部和虚部设置复数类的实部和虚部void CComplex::Set(double r, double i)void CComplex::Set(double r, double i){ {real = r;real = r;imag = i;imag = i;} }第4章 类与对象(duìxiàng)第23页/共64页第二十四页,共65页。
例例例例4.4 4.4 源程序(续二)源程序(续二)源程序(续二)源程序(续二)// // 显示复数显示复数显示复数显示复数(fùshù)(fùshù)值值值值void CComplex::Print()void CComplex::Print(){ {cout << "(" << real << "," << imag << ")" << endl;cout << "(" << real << "," << imag << ")" << endl;} }// // 返回两个复数返回两个复数返回两个复数返回两个复数(fùshù)(fùshù)的相加结果的相加结果的相加结果的相加结果CComplex CComplex::Add(CComplex c)CComplex CComplex::Add(CComplex c){ {CComplex temp;CComplex temp; = real + ; = real + ; = imag + ; = imag + ;return temp;return temp;} }// // 返回复数返回复数返回复数返回复数(fùshù)(fùshù)相减的结果相减的结果相减的结果相减的结果CComplex CComplex::Sub(CComplex c)CComplex CComplex::Sub(CComplex c){ {CComplex temp;CComplex temp; = real - ; = real - ; = imag - ; = imag - ;return temp;return temp;} } 第4章 类与对象(duìxiàng)第24页/共64页第二十五页,共65页。
例例例例4.4 4.4 源程序(续三)源程序(续三)源程序(续三)源程序(续三)void main(void)void main(void){ {CComplex a, b(3.0,4.0), c;CComplex a, b(3.0,4.0), c;CComplex d(b); //CComplex d(b); //调用调用调用调用(diàoyòng)(diàoyòng)复数类的拷贝构造函数复数类的拷贝构造函数复数类的拷贝构造函数复数类的拷贝构造函数cout << "a = ";cout << "a = ";();();cout << "b = ";cout << "b = ";();();cout << "d = ";cout << "d = ";();();c = b.Add(d);c = b.Add(d);d = a.Sub(d);d = a.Sub(d);cout << "c = ";cout << "c = ";();();cout << "d = ";cout << "d = ";();();} } 第4章 类与对象(duìxiàng)程序运行结果程序运行结果(jiē guǒ)(jiē guǒ)为:为:a = (0, 0)a = (0, 0)b = (3, 4)b = (3, 4)d = (3, 4)d = (3, 4)c = (6, 8)c = (6, 8)d = (-3, -4)d = (-3, -4) 返 回第25页/共64页第二十六页,共65页。
4.3 4.3 类的组合类的组合(zǔhé)(zǔhé) 类的组合就是在一个类中内嵌其他类的对象类的组合就是在一个类中内嵌其他类的对象(duìxiàng)(duìxiàng)作为成员,作为成员,因为内嵌对象因为内嵌对象(duìxiàng)(duìxiàng)是该类对象是该类对象(duìxiàng)(duìxiàng)的组成部分,当创建的组成部分,当创建该对象该对象(duìxiàng)(duìxiàng)时,其内嵌对象时,其内嵌对象(duìxiàng)(duìxiàng)也被自动创建也被自动创建 在在C++C++中是通过构造函数的初始化表为内嵌对象中是通过构造函数的初始化表为内嵌对象(duìxiàng)(duìxiàng)初始初始化的组合类带有初始化表的构造函数的定义格式为:化的组合类带有初始化表的构造函数的定义格式为: 类名类名:: ::构造函数构造函数( (参数表参数表) ):内嵌对象:内嵌对象(duìxiàng)1((duìxiàng)1(参数表参数表1)1),内嵌,内嵌对象对象(duìxiàng)2((duìxiàng)2(参数表参数表2)2),,…… { { 构造函数体构造函数体 } } 组合类构造函数的执行顺序为:组合类构造函数的执行顺序为: ((1 1)按内嵌对象)按内嵌对象(duìxiàng)(duìxiàng)的声明顺序依次调用内嵌对象的声明顺序依次调用内嵌对象(duìxiàng)(duìxiàng)的构造函数。
的构造函数 ((2 2)然后执行组合类本身的构造函数然后执行组合类本身的构造函数第4章 类与对象(duìxiàng)第26页/共64页第二十七页,共65页例例例例4.5 4.5 点类点类点类点类CPointCPoint和线段和线段和线段和线段(xiànduàn)(xiànduàn)类类类类CLineCLine#include
例例例例4.5 4.5 点类点类点类点类CPointCPoint和线段和线段和线段和线段(xiànduàn)(xiànduàn)类类类类CLineCLine(续一)(续一)(续一)(续一)CPoint::CPoint(CPoint &p)CPoint::CPoint(CPoint &p){ {X = ;X = ;Y = ;Y = ;cout << " CPoint cout << " CPoint 拷贝拷贝拷贝拷贝(k(kǎ ǎobèi)obèi)构造函数被调用构造函数被调用构造函数被调用构造函数被调用" << endl;" << endl;cout << "(" << X << "," << Y << ")" << endl;cout << "(" << X << "," << Y << ")" << endl;} }class CLineclass CLine{ {public:public:CLine(CPoint p1, CPoint p2);CLine(CPoint p1, CPoint p2);float GetDistance();float GetDistance();private:private:CPoint start;CPoint start;CPoint end;CPoint end;}; }; 第4章 类与对象(duìxiàng)第28页/共64页第二十九页,共65页。
例例例例4.5 4.5 点类点类点类点类CPointCPoint和线段和线段和线段和线段(xiànduàn)(xiànduàn)类类类类CLineCLine(续二)(续二)(续二)(续二)CLine::CLine(CPoint ps, CPoint pe): start(ps), end(pe)CLine::CLine(CPoint ps, CPoint pe): start(ps), end(pe){ {cout << "CLine cout << "CLine 构造函数被调用构造函数被调用构造函数被调用构造函数被调用(diàoyòng)" << endl;(diàoyòng)" << endl;} }float CLine::GetDistance()float CLine::GetDistance(){ {double x = double (() - () );double x = double (() - () );double y = double (() - () );double y = double (() - () );return (float) sqrt(x*x + y*y );return (float) sqrt(x*x + y*y );} }void main()void main(){ { CPoint p1(1,1), p2(4,5);CPoint p1(1,1), p2(4,5);CLine l(p1, p2);CLine l(p1, p2);cout << "The distance is :";cout << "The distance is :";cout << () << endl;cout << () << endl;} } 第4章 类与对象(duìxiàng)程序运行结果为:程序运行结果为:CPoint CPoint 构造函数被调用构造函数被调用CPoint CPoint 构造函数被调用构造函数被调用CPoint CPoint 拷贝构造函数被调用拷贝构造函数被调用((4 4,,5 5))CPoint CPoint 拷贝构造函数被调用拷贝构造函数被调用((1 1,,1 1))CPoint CPoint 拷贝构造函数被调用拷贝构造函数被调用((1 1,,1 1))CPoint CPoint 拷贝构造函数被调用拷贝构造函数被调用((4 4,,5 5))CLine CLine 构造函数被调用构造函数被调用The distance is :5The distance is :5 第29页/共64页第三十页,共65页。
例例例例4.5 4.5 点类点类点类点类CPointCPoint和线段和线段和线段和线段(xiànduàn)(xiànduàn)类类类类CLineCLine(续(续(续(续三)三)三)三)CLineCLine类的对象类的对象l l的构造的构造(gòuzào)(gòuzào)过程:过程:第4章 类与对象(duìxiàng)CLine l(p1, p2)CLine::CLine(CPoint ps, CPoint pe): start(ps) , end(pe){…}CPoint::CPoint(CPoint &p){…}(1)(2)(3)(4) 返 回第30页/共64页第三十一页,共65页4.4 4.4 友元友元 友元提供友元提供(tígōng)(tígōng)了在不同类的成员函数之间、类的成员函数与一般函数了在不同类的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制,友元分为友元函数和友元类之间进行数据共享的机制,友元分为友元函数和友元类 友元函数:一般函数或类的成员函数友元函数:一般函数或类的成员函数 友元类:友元类的所有成员函数都自动成为友元函数友元类:友元类的所有成员函数都自动成为友元函数4.4.1 4.4.1 友元函数友元函数 定义友元函数时,只要在函数原型前加入关键字定义友元函数时,只要在函数原型前加入关键字friendfriend,并将函数原型放,并将函数原型放在类中,格式为:在类中,格式为: friend friend 类型标识符类型标识符 友元函数名(参数列表);友元函数名(参数列表); 友元函数可以是一个普通函数,也可以是其他类的成员函数,在其函数体友元函数可以是一个普通函数,也可以是其他类的成员函数,在其函数体中可以通过对象名直接访问这个类的私有成员。
中可以通过对象名直接访问这个类的私有成员第4章 类与对象(duìxiàng)第31页/共64页第三十二页,共65页例例例例4.6 4.6 定义点类定义点类定义点类定义点类CPointCPoint,写一个,写一个,写一个,写一个(yī (yī ɡ ɡè)è)函数计算两点之间的距离函数计算两点之间的距离函数计算两点之间的距离函数计算两点之间的距离 #include
例例例例4.6 4.6 (续)(续)(续)(续) 将函数将函数GetDistanceGetDistance()声明为()声明为CPointCPoint类的友元将类的友元将CPointCPoint类修改类修改(xiūg(xiūgǎ ǎi) i)如下:如下: class CPoint class CPoint { { public: public: CPoint(int x=0, int y=0); CPoint(int x=0, int y=0); int GetX(); int GetX(); int GetY(); int GetY(); friend double GetDistance(CPoint start, CPoint end); friend double GetDistance(CPoint start, CPoint end); private: private: int X,Y; int X,Y; }; }; 函数函数GetDistanceGetDistance()改写如下:()改写如下: double GetDistance(CPoint start, CPoint end) double GetDistance(CPoint start, CPoint end) { { double d; double d; d = sqrt( (-)*(-) + (-)*(-) ); d = sqrt( (-)*(-) + (-)*(-) ); return d; return d; } } 第4章 类与对象(duìxiàng)第33页/共64页第三十四页,共65页。
4.4 4.4 友元友元4.4.2 友元类 如果一个类(如类A)的很多成员函数都需要经常(jīngcháng)访问另一个类(如类B)的私有成员,可以将类A声明为类B的友元 若A类为B类的友元类,则A类的所有成员函数都是B类的友元函数,都可以访问B类的私有成员 声明友元类的语法形式为: Class B {…… friend class A; // 声明A为B的友元类…… }; 第4章 类与对象(duìxiàng)第34页/共64页第三十五页,共65页例例例例4.7 4.7 友元类的使用友元类的使用友元类的使用友元类的使用(sh(shǐ ǐyòng) yòng) #include
4.4 4.4 友元友元4.4.2 友元类(续) 注意: 友元关系是单向(dān xiànɡ)的:在上面的例子中,B类是A类的友元,所以B类的成员函数可以访问A类的私有成员,但A类不是B类的友元,A类的成员函数不能访问B类的私有成员 友元关系是不能传递的:既如果A类是B类的友元,B类是C类的友元,并不能推断A类是C类的友元第4章 类与对象(duìxiàng) 返 回第36页/共64页第三十七页,共65页4.5 4.5 静态静态(jìngtài)(jìngtài)成员成员4.5.1 静态数据成员 静态数据成员特点:在每个类中只有一个拷贝,由该类的所有对象共同维护和使用,从而实现了同一类的不同对象之间的数据共享 静态数据成员的定义格式:在定义类的成员时前面(qián mian)加static static 类型标识符 静态数据成员名; 在类的声明中仅仅对静态数据成员进行引用性说明,必须在文件作用域的某个地方用类名限定进行定义,这时也可以进行初始化,格式如下: 类型标识符 类名::静态数据成员名 = 初始值; 静态数据成员不属于任何一个对象,可以通过类名直接对它进行访问,一般的用法是: 类名::静态数据成员名第4章 类与对象(duìxiàng)第37页/共64页第三十八页,共65页。
例例例例4.8 4.8 在在在在CStudentCStudent类中添加静态数据成员,保存类中添加静态数据成员,保存类中添加静态数据成员,保存类中添加静态数据成员,保存(b(bǎ ǎocún)CStudentocún)CStudent类的对象总数类的对象总数类的对象总数类的对象总数 #include
例例例例4.7 4.7 (续)(续)(续)(续) int CStudent::total = 0;int CStudent::total = 0;void func();void func();void main()void main(){ {CStudent s1(10001, "AAAAAA" );CStudent s1(10001, "AAAAAA" );cout << s1.GetNumber() << endl;cout << s1.GetNumber() << endl;cout << s1.GetTotal() << endl;cout << s1.GetTotal() << endl;CStudent s2(10002, "BBBBBB" );CStudent s2(10002, "BBBBBB" );cout << s2.GetNumber() << endl;cout << s2.GetNumber() << endl;cout << s1.GetTotal() << endl;cout << s1.GetTotal() << endl;cout << s2.GetTotal() << endl;cout << s2.GetTotal() << endl;func();func();cout << s1.GetNumber() << endl;cout << s1.GetNumber() << endl;cout << s1.GetTotal() << endl;cout << s1.GetTotal() << endl;} }void func()void func(){ {CStudent s3(10003, "CCCCCC" );CStudent s3(10003, "CCCCCC" );cout << s3.GetNumber() << endl;cout << s3.GetNumber() << endl;cout << s3.GetTotal() << endl;cout << s3.GetTotal() << endl;} }第4章 类与对象(duìxiàng)程序运行结果程序运行结果(jiē (jiē guǒ)guǒ)为:为:10001100011 110002100022 22 210003100033 310001100012 210001AAAAAA10002BBBBBB10003CCCCCCnumbernametotal s1 s2 s3 第39页/共64页第四十页,共65页。
4.5 4.5 静态静态(jìngtài)(jìngtài)成员成员4.5.1 静态数据成员(续) 例中,若在主函数中使用下面的语句: cout << CStudent::total << endl; 在编译时就会产生(chǎnshēng)错误信息“不能访问CStudent类的私有成员”,是由于total是类的私有静态成员,类外不能直接访问 如果改写成下面的语句: cout << CStudent::GetTotal() << endl; 仍然有语法错误“GetTotal()不是静态成员函数,调用非法”即不能用类名调用非静态成员函数第4章 类与对象(duìxiàng)第40页/共64页第四十一页,共65页4.5 4.5 静态静态(jìngtài)(jìngtài)成员成员4.5.2 静态成员函数 静态成员函数:在成员函数声明的前面加上关键字static 静态成员函数的特点: (1) 对于公有的静态成员函数,可以通过类名或对象名来调用,而一般(yībān)的非静态成员函数只能通过对象名来调用。
静态成员函数可以由类名通过符号“::”直接调用 (2) 静态成员函数可以直接访问该类的静态数据成员和静态函数成员,不能直接问非静态数据成员和非静态成员函数第4章 类与对象(duìxiàng)第41页/共64页第四十二页,共65页例例例例4.9 4.9 在在在在CStudentCStudent类中添加静态成员类中添加静态成员类中添加静态成员类中添加静态成员(chéngyuán)(chéngyuán)函函函函数数数数#include
例例例例4.8 4.8 (续)(续)(续)(续) int CStudent::total = 0;int CStudent::total = 0;void func();void func();void main()void main(){ {cout << cout << CStudent::GetTotal()CStudent::GetTotal() << endl; << endl;CStudent s1(10001, "AAAAAA" );CStudent s1(10001, "AAAAAA" );cout << CStudent::GetTotal() << endl;cout << CStudent::GetTotal() << endl;CStudent s2(10002, "BBBBBB" );CStudent s2(10002, "BBBBBB" );cout << CStudent::GetTotal() << endl;cout << CStudent::GetTotal() << endl;func();func();cout << CStudent::GetTotal() << endl;cout << CStudent::GetTotal() << endl;} }void func()void func(){ {CStudent s3(10003, "CCCCCC" );CStudent s3(10003, "CCCCCC" );cout << s3.GetTotal() << endl;cout << s3.GetTotal() << endl;} }第4章 类与对象(duìxiàng)程序运行结果程序运行结果(jiē (jiē guǒ)guǒ)为:为:0 01 12 23 32 2可通过类名直接访问静态可通过类名直接访问静态(jìngtài)成员函数,成员函数,这样即使未定义这样即使未定义CStudent类的对象,也可以类的对象,也可以访问静态访问静态(jìngtài)数据成员数据成员total了了 第43页/共64页第四十四页,共65页。
4.5 4.5 静态静态(jìngtài)(jìngtài)成员成员4.5.2 静态成员函数(续) 注意:在静态成员函数中访问(fǎngwèn)非静态数据成员,或非静态成员函数,都会产生语法错误 例如: int CStudent::GetTotal() {cout << number; return total; }第4章 类与对象(duìxiàng)语法错误,不能在静态成员函数中访语法错误,不能在静态成员函数中访语法错误,不能在静态成员函数中访语法错误,不能在静态成员函数中访问非静态数据成员问非静态数据成员问非静态数据成员问非静态数据成员 返 回第44页/共64页第四十五页,共65页4.6 4.6 常对象与常成员常对象与常成员(chéngyuán)(chéngyuán)函数函数 4.6.1 常对象 常对象定义格式(gé shi): const 类名 对象名; 引用对象数组元素的公有成员: 数组名[下标].成员名; 第4章 类与对象(duìxiàng)第45页/共64页第四十六页,共65页。
例例例例4.10 4.10 4.10 4.10 常对象调用常对象调用常对象调用常对象调用(diàoyòng)(diàoyòng)(diàoyòng)(diàoyòng)普通成员函数产生普通成员函数产生普通成员函数产生普通成员函数产生错误错误错误错误 #include
4.6 4.6 常对象与常成员常对象与常成员(chéngyuán)(chéngyuán)函数函数 4.6.2 常成员函数 常成员函数的定义格式(gé shi): 函数类型 函数名(参数列表) const; 例如:float area(float r) const;第4章 类与对象(duìxiàng)第47页/共64页第四十八页,共65页例例例例4.11 4.11 4.11 4.11 使用常成员函数使用常成员函数使用常成员函数使用常成员函数(hánshù)(hánshù)(hánshù)(hánshù)访问常对象中的数据成员访问常对象中的数据成员访问常对象中的数据成员访问常对象中的数据成员 #include
4.6 4.6 常对象常对象(duìxiàng)(duìxiàng)与常与常成员函数成员函数 4.6.2 常成员函数(hánshù)注意: (1)const是函数(hánshù)的一部分,在说明部分和实现部分都要加上关键字const (2)在常成员函数(hánshù)中,不能更新对象的数据成员,也不能调用该类的普通成员函数(hánshù) (3)常对象只能调用常成员函数(hánshù),不能调用该类的普通成员函数(hánshù)普通对象即可以调用普通成员函数(hánshù),也可以调用常成员函数(hánshù),但会优先调用普通成员函数(hánshù)第4章 类与对象(duìxiàng)第49页/共64页第五十页,共65页4.7 4.7 对象对象(duìxiàng)(duìxiàng)数组与对数组与对象象(duìxiàng)(duìxiàng)指针指针4.7.1 对象数组 对象数组:数组中的每一个元素都是类的对象 声明一个一维对象数组的语法形式: 类名 数组名[常量表达式]; 引用(yǐnyòng)对象数组元素的公有成员: 数组名[下标].成员名; 对象数组的初始化:调用构造函数对每个元素初始化 如: CStudent s[3] = { CStudent(10001, "AAAAAA" ), CStudent(10002, "BBBBBB" ), CStudent(10003, "CCCCCC")};第4章 类与对象(duìxiàng)第50页/共64页第五十一页,共65页。
例例例例4.12 4.12 对象对象对象对象(duìxiàng)(duìxiàng)数组的应用数组的应用数组的应用数组的应用#include
例例例例4.12 4.12 (续)(续)(续)(续)void main()void main(){ {int sum=0;int sum=0;CStudent s[5] = { CStudent(10001, "AAAAAA", 20),CStudent s[5] = { CStudent(10001, "AAAAAA", 20), CStudent(10002, "BBBBBB",22 ), CStudent(10002, "BBBBBB",22 ), CStudent(10003, "CCCCCC",24 ), CStudent(10003, "CCCCCC",24 ), CStudent(10004, "DDDDDD",26 ), CStudent(10004, "DDDDDD",26 ), CStudent(10005, "EEEEEE",28 ) CStudent(10005, "EEEEEE",28 ) }; };for(int i=0; i<5; i++)for(int i=0; i<5; i++){ {sum += s[i].GetAge();sum += s[i].GetAge();} }cout << sum/5 << endl;cout << sum/5 << endl;} } 第4章 类与对象(duìxiàng)程序运行结果程序运行结果(jiē (jiē guǒ)guǒ)为:为:2424第52页/共64页第五十三页,共65页。
4.7 4.7 对象对象(duìxiàng)(duìxiàng)数组与数组与对象对象(duìxiàng)(duìxiàng)指针指针4.7.2 对象指针 对象指针:用于存放对象地址的变量 声明对象指针的语法(yǔfǎ)形式: 类名 *对象指针名; 例如: CStudent *p; CStudent s(1001,”AAAAAA”, 20); p = &s; 通过对象指针访问成员的方法为: 对象指针名->成员名第4章 类与对象(duìxiàng)第53页/共64页第五十四页,共65页例例例例4.13 4.13 通过对象指针访问成员,将例主函数通过对象指针访问成员,将例主函数通过对象指针访问成员,将例主函数通过对象指针访问成员,将例主函数(hánshù)(hánshù)改写改写改写改写void main()void main(){ {int sum=0;int sum=0;CStudent *p[5];CStudent *p[5];p[0] = new CStudent(10001, "AAAAAA", 20);p[0] = new CStudent(10001, "AAAAAA", 20);p[1] = new CStudent(10002, "BBBBBB", 22);p[1] = new CStudent(10002, "BBBBBB", 22);p[2] = new CStudent(10003, "CCCCCC", 24);p[2] = new CStudent(10003, "CCCCCC", 24);p[3] = new CStudent(10004, "DDDDDD", 26);p[3] = new CStudent(10004, "DDDDDD", 26);p[4] = new CStudent(10005, "EEEEEE", 28);p[4] = new CStudent(10005, "EEEEEE", 28);for(int i=0; i<5; i++)for(int i=0; i<5; i++){ {sum += sum += p[i]->GetAge();p[i]->GetAge();} }cout << sum/5 << endl;cout << sum/5 << endl;for(i=0; i<5; i++)for(i=0; i<5; i++){ {delete p[i];delete p[i];} }} } 第4章 类与对象(duìxiàng)程序运行结果程序运行结果(jiē (jiē guǒ)guǒ)为:为:2424 返 回第54页/共64页第五十五页,共65页。
4.8 this4.8 this指针指针(zhǐzhēn)(zhǐzhēn) this this指针指针(zhǐzhēn)(zhǐzhēn):类的每个普通成员函数都有一个隐含的:类的每个普通成员函数都有一个隐含的thisthis指针指针(zhǐzhēn)(zhǐzhēn)参数,不需要显示说明参数,不需要显示说明thisthis指针指针(zhǐzhēn)(zhǐzhēn)指向调用该函数的对指向调用该函数的对象例:例: class CPoint class CPoint { { public: public:CPoint(int x=0, int y=0);CPoint(int x=0, int y=0);int GetX();int GetX();int GetY();int GetY(); private: private:int x, y;int x, y; }; }; CPoint::CPoint(int x, int y) CPoint::CPoint(int x, int y) { {x=x;x=x;y=y;y=y; }; }; 第4章 类与对象(duìxiàng)此处的此处的此处的此处的x x和和和和y y都是函数形参中的都是函数形参中的都是函数形参中的都是函数形参中的x x和和和和y y,因为,因为,因为,因为参数是局部变量,在函数体中优先访问参数是局部变量,在函数体中优先访问参数是局部变量,在函数体中优先访问参数是局部变量,在函数体中优先访问(同名覆盖),因此此处无法访问到类成(同名覆盖),因此此处无法访问到类成(同名覆盖),因此此处无法访问到类成(同名覆盖),因此此处无法访问到类成员中的员中的员中的员中的x x和和和和y y可将构造函数改写如下:可将构造函数改写如下:CPoint::CPoint(int x, int y)CPoint::CPoint(int x, int y){ { this -> x=x; this -> x=x; this -> y=y; this -> y=y;}; };定义该类对象:定义该类对象:定义该类对象:定义该类对象:CPoint p(10,20);CPoint p(10,20);第55页/共64页第五十六页,共65页。
例例例例4.14 4.14 定义一个二叉搜索定义一个二叉搜索定义一个二叉搜索定义一个二叉搜索(sōu su(sōu suǒ ǒ) )树,在树中查找指树,在树中查找指树,在树中查找指树,在树中查找指定节点定节点定节点定节点#include
例例例例4.14 4.14 (续一)(续一)(续一)(续一)CTree::CTree(int v)CTree::CTree(int v){ {value = v;value = v;left = NULL;left = NULL;right = NULL;right = NULL;} }CTree::~CTree()CTree::~CTree(){ {if(left)if(left){ {delete left;delete left;left = NULL;left = NULL;} }if(right)if(right){ {delete right;delete right;right = NULL;right = NULL;} }} } 第4章 类与对象(duìxiàng)构造函数用参数构造函数用参数构造函数用参数构造函数用参数v v初始化节点的的值,并将其左节点和右节点都置为空初始化节点的的值,并将其左节点和右节点都置为空初始化节点的的值,并将其左节点和右节点都置为空初始化节点的的值,并将其左节点和右节点都置为空valueleftrightvNULLNULL析构函数使用递归的方法,将该节点以下的节点全部删除。
析构函数使用递归的方法,将该节点以下的节点全部删除析构函数使用递归的方法,将该节点以下的节点全部删除析构函数使用递归的方法,将该节点以下的节点全部删除 第57页/共64页第五十八页,共65页例例例例4.14 4.14 (续二)(续二)(续二)(续二)int CTree::GetValue()int CTree::GetValue(){ {return value;return value;} } void CTree::add(int v)void CTree::add(int v){ {if(v==value) //if(v==value) //保证保证保证保证(b(bǎ ǎozhèng)ozhèng)节点的值不重复节点的值不重复节点的值不重复节点的值不重复return;return;else if(v < value) //else if(v < value) //将小于本节点的值插入左树或左节点将小于本节点的值插入左树或左节点将小于本节点的值插入左树或左节点将小于本节点的值插入左树或左节点{ {if(left != NULL)if(left != NULL)left->add(v); //left->add(v); //用递归方法将值插入左树用递归方法将值插入左树用递归方法将值插入左树用递归方法将值插入左树elseelseleft = new CTree(v); //left = new CTree(v); //新建一个值为新建一个值为新建一个值为新建一个值为v v的节点作为左节点的节点作为左节点的节点作为左节点的节点作为左节点} }elseelse{ {if(right != NULL)if(right != NULL)right->add(v);right->add(v);elseelseright = new CTree(v);right = new CTree(v);} }} } 第4章 类与对象(duìxiàng)将某个值插入到二叉树的合适的位置,本例建立的是二叉树搜索树,节点没有将某个值插入到二叉树的合适的位置,本例建立的是二叉树搜索树,节点没有将某个值插入到二叉树的合适的位置,本例建立的是二叉树搜索树,节点没有将某个值插入到二叉树的合适的位置,本例建立的是二叉树搜索树,节点没有(méi yǒu)(méi yǒu)重复的值,且该节点左边节点的值都小于该节点的值,该节点右边节点的值都大于该节点的值,仍然使用递归的方法将指定的值插入到合适的位置。
重复的值,且该节点左边节点的值都小于该节点的值,该节点右边节点的值都大于该节点的值,仍然使用递归的方法将指定的值插入到合适的位置重复的值,且该节点左边节点的值都小于该节点的值,该节点右边节点的值都大于该节点的值,仍然使用递归的方法将指定的值插入到合适的位置重复的值,且该节点左边节点的值都小于该节点的值,该节点右边节点的值都大于该节点的值,仍然使用递归的方法将指定的值插入到合适的位置 第58页/共64页第五十九页,共65页例例例例4.14 4.14 (续三)(续三)(续三)(续三)CTree* CTree::find(int v)CTree* CTree::find(int v){ {if(v==value)if(v==value)return this;return this;else if(v < value)else if(v < value){ {if(left != NULL)if(left != NULL)return left->find(v);return left->find(v);elseelsereturn NULL;return NULL;} }else else { {if(right != NULL)if(right != NULL)return right->find(v);return right->find(v);elseelsereturn NULL;return NULL;} }} } 第4章 类与对象(duìxiàng)函数函数函数函数findfind()也是使用递归的方法在树中查找指定的值,如查到就返回该节点的指针,否则返回()也是使用递归的方法在树中查找指定的值,如查到就返回该节点的指针,否则返回()也是使用递归的方法在树中查找指定的值,如查到就返回该节点的指针,否则返回()也是使用递归的方法在树中查找指定的值,如查到就返回该节点的指针,否则返回NULLNULL。
因为本函数要返回该节点的指针,因此必须因为本函数要返回该节点的指针,因此必须因为本函数要返回该节点的指针,因此必须因为本函数要返回该节点的指针,因此必须(bìxū)(bìxū)使用使用使用使用thisthis指针,否则没有办法实现指针,否则没有办法实现指针,否则没有办法实现指针,否则没有办法实现第59页/共64页第六十页,共65页例例例例4.14 4.14 (续四)(续四)(续四)(续四)void main()void main(){ {CTree *root;CTree *root;root = new CTree(10);root = new CTree(10);root->add(20);root->add(20);root->add(2);root->add(2);root->add(6);root->add(6);root->add(35);root->add(35);root->add(15);root->add(15);CTree *n1, *n2;CTree *n1, *n2;n1=root->find(6);n1=root->find(6);if(n1)if(n1)cout << n1->GetValue() << endl;cout << n1->GetValue() << endl;elseelsecout << "not found!" << endl;cout << "not found!" << endl;n2=root->find(7);n2=root->find(7);if(n2)if(n2)cout << n2->GetValue() << endl;cout << n2->GetValue() << endl;elseelsecout << "not found!" << endl;cout << "not found!" << endl;delete root;delete root;} }第4章 类与对象(duìxiàng) 返 回1022061535程序运行结果程序运行结果(jiē (jiē guǒ)guǒ)为:为:6 6not found!not found!第60页/共64页第六十一页,共65页。
例例例例4.15 4.15 设计设计设计设计(shèjì)(shèjì)一个栈类一个栈类一个栈类一个栈类 栈是一种栈是一种(yī zh(yī zhǒ ǒn nɡ ɡ) )特殊的线性表,这种线性表只能在固特殊的线性表,这种线性表只能在固定的一端进行插入和删除操作,允许插入和删除的一端称为定的一端进行插入和删除操作,允许插入和删除的一端称为栈顶,另一端称为栈底一个新元素只能从栈顶一端进入,栈顶,另一端称为栈底一个新元素只能从栈顶一端进入,删除时,只能删除栈顶的元素因此栈的运算规则是删除时,只能删除栈顶的元素因此栈的运算规则是“ “先进先进后出后出” ”(或称(或称“ “后进先出后进先出” ”) 栈有三种基本操作:进栈(或入栈),退栈(或出栈)和栈有三种基本操作:进栈(或入栈),退栈(或出栈)和获取栈顶元素获取栈顶元素 对于顺序栈类,进栈操作的方法是先将进栈元素赋给栈顶,对于顺序栈类,进栈操作的方法是先将进栈元素赋给栈顶,然后将栈顶元素下标加然后将栈顶元素下标加1 1。
出栈操作的方法是,将栈顶元素下出栈操作的方法是,将栈顶元素下标减标减1 1 (具体代码参见程序)(具体代码参见程序)第4章 类与对象(duìxiàng)第61页/共64页第六十二页,共65页 例例例例4.16 4.16 设计一个日期类,包含数据成员设计一个日期类,包含数据成员设计一个日期类,包含数据成员设计一个日期类,包含数据成员yearyear、、、、monthmonth、、、、dayday;成员函数有判断;成员函数有判断;成员函数有判断;成员函数有判断(pànduàn)(pànduàn)某年是否伟闰年,某天是当年的第几天,是星期几某年是否伟闰年,某天是当年的第几天,是星期几某年是否伟闰年,某天是当年的第几天,是星期几某年是否伟闰年,某天是当年的第几天,是星期几 分析:计算某天是当年的第几天,只要知道每月由多少天就容易分析:计算某天是当年的第几天,只要知道每月由多少天就容易计算了,如计算了,如1 1、、3 3、、5 5、、7 7、、8 8、、1010、、1212月有月有3131天,天,4 4、、6 6、、9 9、、1111月有月有3030天,天,如果是闰年如果是闰年2 2月有月有2929天,否则天,否则2 2月有月有2828天。
天 计算某天是星期几,首先计算从原点日子(公元前计算某天是星期几,首先计算从原点日子(公元前1 1年年1212月月3131日为日为星期日)到当前日期的天数星期日)到当前日期的天数TotalDaysTotalDays,这个天数应该等于,这个天数应该等于(děngyú)(děngyú)这这段时间经历多少年的总天数加上当年的天数,然后计算段时间经历多少年的总天数加上当年的天数,然后计算TotalDaysTotalDays除以除以7 7的余数,余数是的余数,余数是0 0为星期日、余数是为星期日、余数是1 1为星期一、为星期一、…………余数是余数是6 6为星期为星期六 可用下面的公式计算:可用下面的公式计算:((((year – 1year – 1))* 365 + year / 4 - year / 100 + year / 400 + days* 365 + year / 4 - year / 100 + year / 400 + days))% 7;% 7; 其中其中year-1year-1是经历的整年数,是经历的整年数,year / 4 - year / 100 + year / 400year / 4 - year / 100 + year / 400是经历是经历的闰年数,闰年一次就要增加一天,的闰年数,闰年一次就要增加一天,daysdays是当年经历的天数。
是当年经历的天数 (具体代码参见程序)(具体代码参见程序)第4章 类与对象(duìxiàng)第62页/共64页第六十三页,共65页谢谢 谢!谢!第63页/共64页第六十四页,共65页内容(nèiróng)总结会计学4.1 类与对象4.2 构造函数与析构函数4.3 类的组合(zǔhé)4.4 友元4.5 静态成员4.7 this指针CRect::CRect()CRect::CRect(char *c, int t, int lef, int len, int wid )如CRect类的析构函数声明为:~CRect()谢 谢第六十五页,共65页。
