《C++与C#第三章(续)(精品).ppt》由会员分享,可在线阅读,更多相关《C++与C#第三章(续)(精品).ppt(27页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、1C+与C2 第三章第三章 基于对象的程序设计基于对象的程序设计(续)(续)3Student *ps1=new Student(“lisi”,3,17);delete ps1;/ps1-name并没有删除并没有删除3.6 析构函数析构函数析构函数是构造函数的互补,为生命期即将结束的类对象析构函数是构造函数的互补,为生命期即将结束的类对象自动释放资源自动释放资源。析构函数也是。析构函数也是隐式自动调用隐式自动调用的。的。注意:析构函数的名字是在类名前加上注意:析构函数的名字是在类名前加上波浪线波浪线,它不,它不返回返回任何值任何值也也没有任何参数没有任何参数。尽管我们可以为一个类定义多个构。尽管
2、我们可以为一个类定义多个构造函数,但是我们造函数,但是我们只能提供一个析构函数只能提供一个析构函数,它将被应用在类,它将被应用在类的所有对象上。的所有对象上。class Studentprivate:char*name;int age;int id;4class Studentpublic:Student(const char*str,int i,int a=18);Student();Student(const Student&other);Student();Student:Student()delete name;void main()Student st1(“lisi”,1,17);S
3、tudent *st2=new Student(“zhangsan”,2,19);delete st2;st15class Studentpublic:int getAge()return age;int setAge(int a)age=a;private:char*name;int id;int age;const Student st1(“lisi”,1,18);int age=st1.getAge();st1.setAge(20);?3.7 const成员函数成员函数只有被声明为只有被声明为const 的成员函数的成员函数才能被一个才能被一个const 类对象类对象调用,关键字调用,关
4、键字const 被放在成员函数的参数表和函数体之被放在成员函数的参数表和函数体之间间,对于在类体之外定义的,对于在类体之外定义的const 成员函数,我们必须在成员函数,我们必须在它的定义和声明中同时指定关键字它的定义和声明中同时指定关键字const6class Studentpublic:int getAge()const return age;int setAge(int a)age=a;int getId()const;private:char*name;int id;int age;int Student:getId()constreturn id;const Student st1(
5、“lisi”,1,18);int age=st1.getAge();int id=st1.getId();int setAge(int a)const age=a;把一个修改类数据成员的函数声明为把一个修改类数据成员的函数声明为const 是非法的是非法的7为了允许修改一个为了允许修改一个const对象的数据成员,可把相应的对象的数据成员,可把相应的数据成员声明为数据成员声明为mutableclass Studentpublic:int getAge()const return age;int setAge(int a)const age=a;int getId()const;private:
6、char*name;int id;mutable int age;8统计创建的所有学生对象的个数?统计创建的所有学生对象的个数?学生人数不是任何一个具体学生的属性,具有全局性学生人数不是任何一个具体学生的属性,具有全局性若用一个全局变量记录学生人数,缺点:若用一个全局变量记录学生人数,缺点:容易被误修改,不安全。容易被误修改,不安全。容易和其它全局变量重名。容易和其它全局变量重名。3.8 static成员成员9静态数据成员被当作静态数据成员被当作类的全局对象类的全局对象,对于非静态数据成员,每,对于非静态数据成员,每个类对象都有自己的拷贝,而个类对象都有自己的拷贝,而静态数据成员对每个类只有一
7、个静态数据成员对每个类只有一个拷贝拷贝,由该,由该类的所有对象共享类的所有对象共享访问。访问。student.hclass Studentpublic:Student();Student();private:char*name;int id;mutable int age;static int count;student.cpp#include“student.h”int Student:count=0;Student:Student()count+;Student:Student()count-;friend int getCount();int getCount()return Stude
8、nt:count;10class Studentpublic:static int getCount()return count;private:char*name;int id;mutable int age;static int count;int count=Student:getCount();在静态成员函数中只能访问静态成员。在静态成员函数中只能访问静态成员。11class Studentpublic:private:char*name;int id;mutable int age;static int count;static const int class=3306;只有静态整型
9、只有静态整型常量才能在头常量才能在头文件里初始化文件里初始化static const char depart20=“CSE”;123.9 操作符重载操作符重载int a,b,c;a=1;b=1;c=1;a=b=c=1;classString public:private:int _size;char*_string;String s1,s2,s3,s4;s1=s2=s3=s4=“hello”;?13重载操作符使得重载操作符使得类对象可以与操作符一起被使用类对象可以与操作符一起被使用,使得对类对象,使得对类对象的操纵与内置类型的对象一样直观。的操纵与内置类型的对象一样直观。重载的操作符在类体中被
10、声明,声明方式同普通成员函数一样,重载的操作符在类体中被声明,声明方式同普通成员函数一样,只不过它的名字包含只不过它的名字包含关键字关键字operator,以及紧随其后的一个,以及紧随其后的一个预预定义操作符:定义操作符:3.9 操作符重载操作符重载14class String public:String&operator=(const char*sobj);private:int _size;char*_string;String&String:operator=(const char*sobj)if(!sobj)_size=0;delete _string;_string=0;else _
11、size=strlen(sobj);delete _string;_string=new char _size+1;strcpy(_string,sobj);return*this;String&operator=(const String&);String s1,s2,s3;s1=s2=s3=“hello”;15class String public:String&operator=(const char*sobj);private:int _size;char*_string;class String friend String&operator=(String&,const char*)
12、;private:int _size;char*_string;String&operator=(String&str,const char*sobj);16注意:注意:对于内置类型的操作符,它的预定义意义不能被改变;对于内置类型的操作符,它的预定义意义不能被改变;/错误错误:不能为不能为int 重新定义内置的操作符重新定义内置的操作符int operator+(int,int);不能为内置数据类型定义其他的操作符;不能为内置数据类型定义其他的操作符;预定义的操作符预定义的操作符优先级不能被改变优先级不能被改变。173.10 类的组合类的组合问题:问题:定义一个类,描述一条线段定义一个类,描述
13、一条线段 线段具有长度、两个端点等属性线段具有长度、两个端点等属性 线段具有求长度等行为线段具有求长度等行为端点可以用另外一个表示点的类表示端点可以用另外一个表示点的类表示线段类线段类Line包含两个点类包含两个点类Point的对象的对象18类的组合描述的是一个类的组合描述的是一个类内嵌其他类的对象类内嵌其他类的对象作为成作为成员的情况,它们之间的关系是一种员的情况,它们之间的关系是一种包含与被包含包含与被包含的的关系。关系。class Pointpublic:Point(int xx=0,int yy=0)X=xx;Y=yy;Point(Point&p);int GetX()return X
14、;int GetY()return Y;private:int X,Y;class Linepublic:Line(Point xp1,Point xp2);Line(Line&);double GetLen()return len;private:Point p1,p2;double len;19当创建类的对象时,当创建类的对象时,如果这个类具有内嵌对象成员,如果这个类具有内嵌对象成员,那么各个内嵌对象将首先被自动创建那么各个内嵌对象将首先被自动创建。因此,在创。因此,在创建对象时,既要对本类的基本类型数据成员进行初建对象时,既要对本类的基本类型数据成员进行初始化,又要对内嵌对象成员进行初始
15、化。始化,又要对内嵌对象成员进行初始化。Point:Point(Point&p)X=p.X;Y=p.Y;Line:Line(Point xp1,Point xp2):p1(xp1),p2(xp2)double x=(double)(p1.GetX()-p2.GetX();double y=(double)(p1.GetY()-p2.GetY();len=sqrt(x*x+y*y);Line:Line(Line&L):p1(L.p1),p2(L.p2)len=L.len;20int main()Point myp1(1,1),myp2(4,5);Line line(myp1,myp2);Line
16、 line2(line);cout“The length of the line is:”;coutline.GetLen()endl;cout“The length of the line2 is:”;coutline2.GetLen()endl;如何调用如何调用Line和和Point的构造函数的构造函数?调用顺序?调用顺序?21在创建一个组合类的对象时,不仅它自身的构造函数将被调用,在创建一个组合类的对象时,不仅它自身的构造函数将被调用,而且还将调用其内嵌对象的构造函数,调用顺序为:而且还将调用其内嵌对象的构造函数,调用顺序为:1、调用内嵌对象的构造函数调用内嵌对象的构造函数,调用顺序按照
17、内嵌对象在组合类的,调用顺序按照内嵌对象在组合类的声明中出现的次序。声明中出现的次序。2、执行本类的构造函数执行本类的构造函数。析构函数的调用顺序与构造函数刚好相反。析构函数的调用顺序与构造函数刚好相反。22Point:Point(Point&p)X=p.X;Y=p.Y;Line:Line(Point xp1,Point xp2):p1(xp1),p2(xp2)double x=(double)(p1.GetX()-p2.GetX();double y=(double)(p1.GetY()-p2.GetY();len=sqrt(x*x+y*y);Line:Line(Line&L):p1(L.p
18、1),p2(L.p2)len=L.len;int main()Point myp1(1,1),myp2(4,5);Line line(myp1,myp2);Line line2(line);cout“The length of the line is:”;coutline.GetLen()endl;cout“The length of the line2 is:”;coutline2.GetLen()bMethod();private:B*x;B y;class Bpublic:void bMethod();private:A*z;前向引用声明虽然可以解决一些问前向引用声明虽然可以解决一些问题
19、,但它题,但它不是万能不是万能的。尽管使用了的。尽管使用了前向引用声明,但在提供一个完整前向引用声明,但在提供一个完整的类声明之前,的类声明之前,不能声明该类的对不能声明该类的对象象,也,也不能在内联成员函数中使用不能在内联成员函数中使用该类的对象该类的对象。26class MyString public:MyString(const char*=0);MyString(const MyString&);MyString();MyString&operator=(const MyString&);/赋值操作符的重载赋值操作符的重载char&operator(int)const;/重载下标操作符
20、重载下标操作符bool operator=(const MyString&)const;/比较操作符重载比较操作符重载bool operator (const MyString&)const;MyString&operator+=(const MyString&);/将两个字符串相连将两个字符串相连private:int size;char*myStr;作业(作业(3月月28日之前提交):日之前提交):修改上次作业修改上次作业MyString类的定义和实现,如下:类的定义和实现,如下:27class MyString public:MyString(const char*str=0);MySt
21、ring(const MyString&str);MyString();char getCh(int i);/取得下标为取得下标为i的字符,下标从的字符,下标从0开始,若不存在,返回开始,若不存在,返回0bool setCh(int i,char ch);/将下标为将下标为i的字符设置为的字符设置为ch,/若存在下标为若存在下标为i的元素,返回的元素,返回true,否则返回,否则返回false。void copy(const MyString&str);/拷贝拷贝str的内容(替换已有字符串)的内容(替换已有字符串)void copy(const char*str);void strCat(const MyString&str);/将将str的内容追加到已有字符串之后的内容追加到已有字符串之后void strCat(const char*str);int getSize();/取得字符串长度取得字符串长度void print();/直接打印输出,不加回车换行符直接打印输出,不加回车换行符private:int size;char*myStr;
限制150内