C++程序设计教程课件.ppt
《C++程序设计教程课件.ppt》由会员分享,可在线阅读,更多相关《C++程序设计教程课件.ppt(52页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C+程序设计教程(第二版)第九章 对象生灭 1/11/20231第九章内容1.构造函数设计构造函数设计2.构造函数的重载构造函数的重载3.类成员初始化类成员初始化4.构造顺序构造顺序5.拷贝构造函数拷贝构造函数6.析构函数析构函数7.对象转型与赋值对象转型与赋值1/11/202321.构造函数设计构造函数设计初始化要求 定义一个对象,其形式与定义一个变量相似,但更具意义。对象与变量的不同在于对象对应于事物,要求从诞生之时起便有明确的意义.对象必须建立一种初始化机制,以满足在编程中可以针对实际问题所提出的要求而赋给一个有意义的初值。创建一个对象,若创建的是全局对象,则以全0的模式表示对象,若创建
2、局部对象,则以随机值表示对象。1/11/20233 对象的初始化不是简单的参数与成员对应,而是联系参数到成员的过程.封装性要求Struct Point int x,y;Point d=2,3;class Point int x,y;/;Point d=2,3;正确错误 封装性的要求杜绝了这种初始化形式,事实上,这种形式根本不能完成对象的初始化过程中的校验和计算工作。对象通常是一个复杂的实体,在构建对象过程中,并不一定是一个初值对应一个对象分量。许多时候,一个初值只是传递一个信息,告诉对象的创建工作应怎么进行。封装性要求对象创建中按传递的信息进行一个过程化的初始化工作。1/11/20234函数形
3、式构造函数(constructor)是与类名同名的特殊的成员函数,当定义该类的对象时,构造函数将被自动调用以实现对该对象的初始化。构造函数不能有返回值,因而不能指定包括void在内的任何返回值类型。构造函数的定义体可与其它成员函数成员一样,放在类内或类外都可。构造函数的定义格式为:类名(形参说明)类名(形参说明)函数体函数体 构造函数既可定义成有参函数,也可义成无参函数,要根据问题的需要来定。全局变量和静态变量在定义时,将自动赋初值为0;局部变量在定义时,其初始值不固定的。而当对象被定义时,由于对象的意义表达了现实世界的实体,所以一旦定义对象,就必须有一个有意义的初始值,在C+中,在定义对象的
4、同时,给该对象初始化的方法就是利用构造函数。1/11/20235例:类person包括4个数据成员,用来记录人员信息。生成对象obj,并使用构造函数为obj赋予初始值。#include#include class Person /定义类 private:/类Person的数据成员 char name 10;/姓名 int age;/年龄 int salary;/薪金 char tel8;/电话public:/构造函数Person Person(char*xname,int xage,int xsalary,char *xtel);void disp();/函数Person的定义Person:P
5、erson(char*xname,int xage,int xsalary,char*xtel)strcpy(name,xname);/给各数据成员提供初值 age=xage;salary=xsalary;strcpy(tel,xtel);1/11/20236/函数disp的定义void Person:disp()coutendl;cout 姓名:name endl;cout 年龄:age endl;cout 工资:salary endl;cout 电话:tel endlendl;/主函数void main()/生成对象obj并初始化 Person obj(张立三,25,850,4567231
6、4);/显示obj obj.disp();1/11/20237程序的执行结果是:姓名:张立三 年龄:25 工资:850 电话:45672314在主函数中的Person obj(张立三,25,850,45672314);中完成了以下几个功能:1.定义并生成了对象obj。2.在生成对象obj的同时,自动调用相应类的构造函数Person3.将初始值张立三,25,850,45672314传递给构造函数Person相应的形参xname,xage,xsalary,xtel。4.执行构造函数体,将相应的值赋给相应的数据成员。1/11/20238一次性对象 创建对象时如果不给出对象名,直接以类名调用构造函数,
7、则产生一个无名对象。无名对象经常在参数传递时使用。例如:coutDate(2003,12,23);Date(2003,12,23)是一个对象,该对象在做了操作后便烟消云散了,所以这种对象一般用在创建后不需要反复使用的场合。1/11/202392.构造函数重载构造函数重载 构造函数毕竟是函数,是函数就可以重载。不但可以重载,还可以设置默认参数。如果一个类中出现了两个以上的同名的成员函数时,称为类的成员函数的重载。class Datepublic:Date(const string&s);/重载 Date(int y=2003,int m=12,int d=1);/参数默认 /.;int main
8、()Date d(“2006-12-26”);Date e(2000,12,25);Date f(2001,10);Date g(2002);Date h;/.1/11/202310 Date h;这行代码似乎是一个错误,对于对象的创建,即对于无参的构造函数的调用,应该是g(),加上类名,即写成:Date g();但是,从语法上来讲,这个语句也是名叫g的返回临时Date对象的函数声明!因此,C+语言在设计时,为了区别无初始化的对象定义和返回类对象的无参函数声明的差别,也为了保持无初始化变量定义与无初始化(无参)对象定义的一致性,规定无参对象定义语句为:int a;/变量定义int b;/返回整
9、型值的无参函数声明Date g;/无参对象定义,加空括号后就成了无参函数声明Date g();/返回类对象的无参函数声明1/11/202311 对于返回对象值的有参函数声明和有初始化的对象定义语句,由于函数声明中的参数有类型引导,而对象定义的初始化中无类型引导,它们本身(或在编译器看来)是可以区分的:Date e(2002);/对象定义Date e(int y);/函数声明1/11/202312 C+规定,每个类必须有一个构造函数。如果在类中没有显式定义构造函数时,则C+编译系统在编译时为该类提供一个默认的构造函数,该默认构造函数是个无参函数,它仅负责创建对象,而不做任何初始化工作。class
10、 Datepublic:/相当于定义了Date();int main()Date d;/ok /.与变量定义相似,在用默认构造函数创建对象时,如果创建的是全局对象或静态对象,则对象的默认值为0,否则对象的初始值是不定的。1/11/202313只要一个类定义了一个构造函数(不一定是无参构造函数),C+编译系统就不再提供默认的构造函数。任何其他的构造函数定义,都将阻止默认无参空函数的产生:class Datepublic:Date(int y,int m,int d)/.;int main()Date d;/error /.1/11/202314 当构造函数有缺省参数时,称为具有缺省参数的构造函数
11、,在使用时要防止二义性。如:class Myclass /定义类Myclass private:int member;public:Myclass();Myclass(int i);Myclass:Myclass()/构造函数Myclass member=10;1/11/202315Myclass:Myclass(int i=10)/构造函数Myclass(int i),该函数 /的形参i为缺省参数 member=i;void main()Myclass x(20);Myclass y;/产生二义性,无法确定自动调用哪个构造 /函数完成对象的构造 1/11/202316回顾:上节课主要讲了构造
12、函数的概念、意义及定义方式、构造函数的重载。1/11/2023173.类成员初始化类成员初始化默认调用的无参构造函数 在类定义中有数据成员和成员函数,数据成员可以是内部数据类型的变量实体,也可以是对象实体。如果一个类A的对象作为另一个类B的数据成员,则在类B的对象创建过程中,调用其构造函数的过程中,数据成员(类A的对象)会自动调用类A的构造函数。这样就会面临一些问题。例:有一个学号类和一个学生类,学生类中包含了学号类的对象,因此在构造学生类对象时,面临着学号类对象的构造。1/11/202318class StudentID int value;public:StudentID()static
13、int nextStudentID=0;value=+nextStudentID;coutAssigning student id valuen;/-class Student string name;StudentID id;public:Student(string n=noName)cout Constructing student +n+n;name=n;/-int main()Student s(Randy);/=在学生类的构造函数中并没有看到学号类对象初始化的痕迹,而数据成员name倒被赋了初值。从运行的结果看,当学生类对象被构造时,一个学号对象也创建了,而且学号类的构造函数先于学
14、生类对象的构造函数体的执行而执行。1/11/202319对于对于Student s(“Randy”);其内部的其内部的 执行顺序是这样的:执行顺序是这样的:(1)先分配学生类对象先分配学生类对象s的空间,调用的空间,调用Student构造函数;构造函数;(2)在在Student构造函数体尚未执行时,由于看到了类的对象构造函数体尚未执行时,由于看到了类的对象成员成员ID,转而去调用学号类的无参构造函数;相当于执行定转而去调用学号类的无参构造函数;相当于执行定义语句:义语句:StudentID id;(3)执行了学号类构造函数体,输出结果的第执行了学号类构造函数体,输出结果的第1行信息,返回行信息
15、,返回到到Student构造函数;构造函数;(4)执行执行Student构造函数体,输出结果的第构造函数体,输出结果的第2行信息,完成行信息,完成全部构造工作。全部构造工作。说明:先成员构造,后自身构造成员构造不见显式调用,而是悄悄调用无参构造函数对学号类构造函数的调用时默认的,默认调用便是调用无参构造函数,而正好学号类设计的构造函数就是无参构造函数。1/11/202320初始化的困惑 在刚刚的实例中,只是初始化了名称,而没有给定学号。如果,在学生对象创建中,既要初始化名称,又要给定一个指定的初始化学号,也就是不要默认调用无参构造函数,那么类该如何操作呢?如果不能在创建StudentID的过程
16、中初始化对象,就不能将对象值设置到位。下面给出一个不正确的初始化尝试,还是对刚才的例子作修改:1/11/202321class StudentID int value;public:StudentID(int id=0)value=id;coutAssigning student id valuen;/-class Student string name;StudentID id;public:Student(string n=noName,int ssID=0)cout Constructing student +n+n;name=n;StudentID id(ssID);/-int mai
17、n()Student s(Randy,58);/=运行结果:1/11/202322 S对象初始化的学号为58,重新设计了Student构造函数,将该值传递给了它,所以形参ssID的值也为58。但是我们看到转而调用的StudentID构造函数执行体却没有输出58,而是默认的0学号。这说明转而调用的仍然是无参构造函数。将StudentID的构造函数写成参数默认是为了让无参构造函数调用也能通过,以便让整个程序顺利运行。乃至后来,要想在Student类内,通过构造函数体中的对象初始化创建的定义语句来改变id的值,发现这仅仅只是区别于s对象中的id对象的一个局部对象,等到构造函数结束时,该局部对象的局部
18、生命期到期而不销毁。1/11/202323 如果一个类A的对象作为另一个类B的数据成员,则在类B的对象创建过程中,调用其构造函数的过程中,数据成员(类A的对象)会自动调用类A的构造函数。如果类A的构造函数为有参函数时,则在程序中必须在类B的构造函数的括号后面加一“:”和被调用的类A的构造函数,且调用类A的构造函数时的实参值必须来自类B的形参表中的形参。这种方法称为初始化表的方式调用构造函数。这种在构造函数的参数列表的右括号后面,花括号前面,用冒号引出构造函数的调用表,可以省略类型名称,但却行创建对象之职。初始化表调用构造函数1/11/202324 类X的构造函数的定义格式应为:X:X(参数表0
19、):成员1(参数表1),成员2(参数表2),成员n(参数表n)其中,参数表1提供初始化成员1所需的参数,参数表2提供初始化成员2所需的参数,依此类推。并且这几个参数表的中的参数均来自参数表0,另外,初始化X的非对象成员所需的参数,也由参数表0提供。在构造新类的对象过程中,系统首先调用其子对象的构造函数,初始化子对象;然后才执行类X自己的构造函数,初始化类中的非对象成员。对于同一类中的不同子对象,系统按照它们在类中的说明顺序调用相应的构造函数进行初始化,而不是按照初始化表的顺序。1/11/202325例:#includeusing namespace std;/-class StudentID
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 程序设计 教程 课件
限制150内