《面向对象程序设计第5章.ppt》由会员分享,可在线阅读,更多相关《面向对象程序设计第5章.ppt(69页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第5章章 继承继承(inheritance)5.1 类层次结构类层次结构类层次结构类层次结构5.2 基类与派生类基类与派生类 l l几个概念:几个概念:几个概念:几个概念:l l基类(父类)基类(父类)基类(父类)基类(父类)l l派生类(子类):从基类派生而成的类派生类(子类):从基类派生而成的类派生类(子类):从基类派生而成的类派生类(子类):从基类派生而成的类l l基类和派生类:构成类的层次关系基类和派生类:构成类的层次关系基类和派生类:构成类的层次关系基类和派生类:构成类的层次关系哺乳类哺乳类哺乳类哺乳类猫科猫科猫科猫科基类基类基类基类 baseclassbaseclass派生类派生
2、类派生类派生类derivedclassderivedclass派生类的定义派生类的定义对于基类对于基类对于基类对于基类PersonPerson,可以这样来定义:,可以这样来定义:,可以这样来定义:,可以这样来定义:classPersonclassPerson/./.;派生类在声明的时候,必须在类名和类的本体之间加上冒号派生类在声明的时候,必须在类名和类的本体之间加上冒号派生类在声明的时候,必须在类名和类的本体之间加上冒号派生类在声明的时候,必须在类名和类的本体之间加上冒号“:”,publicpublic(继承方式)以及基类的名称。下面定义(继承方式)以及基类的名称。下面定义(继承方式)以及基类
3、的名称。下面定义(继承方式)以及基类的名称。下面定义基类基类基类基类PersonPerson的派生类的派生类的派生类的派生类StudentStudent:classStudent:publicPersonclassStudent:publicPerson/./.;5.3 派生类对象的构造派生类对象的构造 l l5.3.15.3.1派生类对象的内存空间派生类对象的内存空间派生类对象的内存空间派生类对象的内存空间 实际上,在前面的继承关系里面,派生类实际上,在前面的继承关系里面,派生类实际上,在前面的继承关系里面,派生类实际上,在前面的继承关系里面,派生类StudentStudent包包包包含了基
4、类含了基类含了基类含了基类PersonPerson的一个子对象,就像在的一个子对象,就像在的一个子对象,就像在的一个子对象,就像在StudentStudent中创建中创建中创建中创建PersonPerson的一个对象,而不从的一个对象,而不从的一个对象,而不从的一个对象,而不从PersonPerson中继承一样。无论中继承一样。无论中继承一样。无论中继承一样。无论是类中的对象成员还是基类部分,都被认为是子对象。是类中的对象成员还是基类部分,都被认为是子对象。是类中的对象成员还是基类部分,都被认为是子对象。是类中的对象成员还是基类部分,都被认为是子对象。例例 5-1 派生类派生类Student的
5、定义的定义#include#include#include#include usingnamespacestd;usingnamespacestd;classclassPersonPersonprivate:private:charName20;charName20;intintAge;Age;charSex;charSex;/./.其它的属性其它的属性其它的属性其它的属性publicpublic:personperson(char(char*pNamepName=NoName,=NoName,intintpAgepAge=0,char=0,charpSexpSex=M)=M)strcpy(N
6、ame,pNamestrcpy(Name,pName););Age=Age=pAgepAge;Sex=Sex=pSexpSex;voidvoidSet(charSet(char*pNamepName=NoName,=NoName,intint pAgepAge=0,char=0,charpSexpSex=M)=M)strcpy(Name,pNamestrcpy(Name,pName););Age=Age=pAgepAge;Sex=Sex=pSexpSex;char*char*GetNameGetName()()returnName;returnName;intint GetAgeGetAge(
7、)()returnAge;returnAge;charcharGetSexGetSex()()returnSex;returnSex;voidDisplay()voidDisplay()coutcoutName:Name,Age:AgeName:Name,Age:Age,Sex:Sex,Sex:Sexendlendl;classclassStudent:Student:publicpublicpersonperson protectedprotected:charMajor40;charMajor40;unsignedunsignedintint IdNumberIdNumber;unsign
8、edunsignedintintLevel;Level;publicpublic:char*char*GetMajorGetMajor()()returnMajor;returnMajor;unsignedunsignedintint GetIdNumberGetIdNumber()()returnreturnIdNumberIdNumber;unsignedunsignedintint GetLevelGetLevel()()returnLevel;returnLevel;intintmain()main()PersonPersonper(Zhangper(ZhangHong,20,F);H
9、ong,20,F);StudentStudentstustu;per.Displayper.Display();();stu.Displaystu.Display();();per.Set(Wangper.Set(WangLin,18,F);Lin,18,F);stu.Set(Zhaostu.Set(ZhaoWei,21,M);Wei,21,M);per.Displayper.Display();();stu.Displaystu.Display();();return0return0;程序运行结果如下:程序运行结果如下:程序运行结果如下:程序运行结果如下:Name:ZhangName:Zha
10、ng Hong,Age:20,Sex:F Hong,Age:20,Sex:FName:NoName:No Name,Age:0,Sex:M Name,Age:0,Sex:MName:WangName:Wang Lin,Age:18,Sex:F Lin,Age:18,Sex:FName:ZhaoName:Zhao Wei,Age:21,Sex:M Wei,Age:21,Sex:M 例例例例 5-2 5-2 重新定义派生类重新定义派生类重新定义派生类重新定义派生类StudentStudent中的中的中的中的SetSet和和和和DisplayDisplay函数函数函数函数 classclassStu
11、dent:Student:publicpublicPersonPerson protected:protected:charMajor40;charMajor40;unsignedunsignedintint IdNumberIdNumber;unsignedunsignedintintLevel;Level;public:public:char*char*GetMajorGetMajor()()returnMajor;returnMajor;unsignedunsignedintint GetIdNumberGetIdNumber()()returnreturnIdNumberIdNumbe
12、r;unsignedunsignedintint GetLevelGetLevel()()returnLevel;returnLevel;voidvoidSet(charSet(char*pMajorpMajor=0,=0,unsignedunsignedintint pIdNumberpIdNumber=0,=0,unsignedunsignedintint pLevelpLevel=0)=0)strcpy(Major,pMajorstrcpy(Major,pMajor););IdNumberIdNumber=pIdNumberpIdNumber;Level=Level=pLevelpLev
13、el;voidvoidSet(charSet(char*pName,intpName,int pAge,charpAge,char pSexpSex,char*char*pMajor,unsignedpMajor,unsigned intint pIdNumberpIdNumber,unsignedunsignedintint pLevelpLevel)Person:Set(pName,pAge,pSexPerson:Set(pName,pAge,pSex););strcpy(Major,pMajorstrcpy(Major,pMajor););IdNumberIdNumber=pIdNumb
14、erpIdNumber;Level=Level=pLevelpLevel;voidDisplay()voidDisplay()Person:DisplayPerson:Display();();coutcoutIdNumberIdNumber:IdNumberIdNumber,Major:Major,Major:Major,Level:Level,Level:Levelendlendl;voidmain()voidmain()PersonPersonper(Zhangper(ZhangHong,20,F);Hong,20,F);StudentStudentstustu;per.Displayp
15、er.Display();();stu.Displaystu.Display();();per.Set(Wangper.Set(WangLin,18,F);Lin,18,F);stu.Set(Computer,1001,2);stu.Set(Computer,1001,2);per.Displayper.Display();();stu.Displaystu.Display();();输出结果输出结果Name:ZhangName:Zhang Hong,Age:20,Sex:F Hong,Age:20,Sex:FName:NoName:No Name,Age:0,Sex:M Name,Age:0
16、,Sex:MIdNumber:3435973836,Major:IdNumber:3435973836,Major:烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫Zhang HoZhang Hong,Level:3435973836ng,Level:3435973836Name:WangName:Wang Lin,Age:18,Sex:F Lin,Age:18,Sex:FName:NoName:No Name,Age:0,Sex:M Name,Age:0,Sex:MIdNumber:1001,Major:Computer,Lev
17、el:2IdNumber:1001,Major:Computer,Level:2重新定义(重新定义(redefinition)重新定义并非重载,对基类重新定义并非重载,对基类重新定义并非重载,对基类重新定义并非重载,对基类PersonPerson的的的的SetSet和和和和DisplayDisplay函数而函数而函数而函数而言,它们位于言,它们位于言,它们位于言,它们位于基类的类域基类的类域基类的类域基类的类域中,所以通过基类对象中,所以通过基类对象中,所以通过基类对象中,所以通过基类对象perper调用调用调用调用SetSet和和和和DisplayDisplay的时候调用的是基类的这两个函数
18、,同样对于派生类的时候调用的是基类的这两个函数,同样对于派生类的时候调用的是基类的这两个函数,同样对于派生类的时候调用的是基类的这两个函数,同样对于派生类StudentStudent的的的的SetSet和和和和DisplayDisplay函数而言,它们位于函数而言,它们位于函数而言,它们位于函数而言,它们位于派生类的类域派生类的类域派生类的类域派生类的类域中,中,中,中,所以通过派生类类对象所以通过派生类类对象所以通过派生类类对象所以通过派生类类对象stustu调用调用调用调用SetSet和和和和DisplayDisplay的时候调用的是派的时候调用的是派的时候调用的是派的时候调用的是派生类的
19、生类的生类的生类的SetSet和和和和DisplayDisplay函数。现在用函数。现在用函数。现在用函数。现在用StudentStudent类定义一个名字还是类定义一个名字还是类定义一个名字还是类定义一个名字还是叫叫叫叫stustu的对象:的对象:的对象:的对象:StudentStudentstustu;下面的两个函数调用:下面的两个函数调用:下面的两个函数调用:下面的两个函数调用:stu.Set(Zhaostu.Set(ZhaoWei,20,M,Computer,Wei,20,M,Computer,1001,2);1001,2);stu.GetIdNumberstu.GetIdNumber
20、();();stu.Displaystu.Display();();调用的都是派生类调用的都是派生类调用的都是派生类调用的都是派生类StudentStudent中新定义的成员函数。由于中新定义的成员函数。由于中新定义的成员函数。由于中新定义的成员函数。由于GetAgeGetAge和和和和GetNameGetName函数在没有重新定义,所以,函数在没有重新定义,所以,函数在没有重新定义,所以,函数在没有重新定义,所以,stu.GetAgestu.GetAge();();stu.GetNamestu.GetName();();所调用的仍是基类所调用的仍是基类所调用的仍是基类所调用的仍是基类Pers
21、onPerson中原有的成员函数。中原有的成员函数。中原有的成员函数。中原有的成员函数。覆盖覆盖 如果在基类存在这样的重载函数:如果在基类存在这样的重载函数:如果在基类存在这样的重载函数:如果在基类存在这样的重载函数:voidSet();voidSet();voidvoidSet(charSet(char*,*,int,charint,char););同时在派生类中对同时在派生类中对同时在派生类中对同时在派生类中对SetSet函数进行了重新定义,函数进行了重新定义,函数进行了重新定义,函数进行了重新定义,StatusStatusSet(charSet(char*,*,int,charint,c
22、har););即使函数的返回值类型不一样。基类中的所有名为即使函数的返回值类型不一样。基类中的所有名为即使函数的返回值类型不一样。基类中的所有名为即使函数的返回值类型不一样。基类中的所有名为SetSet的函数的函数的函数的函数也都将被覆盖,也就是说,派生类的对象无法再调用基类的也都将被覆盖,也就是说,派生类的对象无法再调用基类的也都将被覆盖,也就是说,派生类的对象无法再调用基类的也都将被覆盖,也就是说,派生类的对象无法再调用基类的同名函数同名函数同名函数同名函数SetSet。即:。即:。即:。即:stu.Setstu.Set();();编译器将会报错。编译器将会报错。编译器将会报错。编译器将会
23、报错。可以在派生类的成员函数内部通过使用类名和可以在派生类的成员函数内部通过使用类名和可以在派生类的成员函数内部通过使用类名和可以在派生类的成员函数内部通过使用类名和作用域解析符作用域解析符作用域解析符作用域解析符“:”来调用基类的成员函数,从而来调用基类的成员函数,从而来调用基类的成员函数,从而来调用基类的成员函数,从而改变或者显示基类的数据成员。当然,也可以定义专改变或者显示基类的数据成员。当然,也可以定义专改变或者显示基类的数据成员。当然,也可以定义专改变或者显示基类的数据成员。当然,也可以定义专门用于取用基类中数据的成员函数:门用于取用基类中数据的成员函数:门用于取用基类中数据的成员函
24、数:门用于取用基类中数据的成员函数:voidvoidSetPersonSetPerson()()Person:SetPerson:Set();();voidvoidDisplayPersonDisplayPerson()()Person:DisplayPerson:Display();();这里需要注意函数的名字不能使用这里需要注意函数的名字不能使用这里需要注意函数的名字不能使用这里需要注意函数的名字不能使用SetSet和和和和DisplayDisplay,原因在前面刚提到过,因为在派生类中,原因在前面刚提到过,因为在派生类中,原因在前面刚提到过,因为在派生类中,原因在前面刚提到过,因为在派生
25、类中已经对已经对已经对已经对SetSet和和和和DisplayDisplay函数进行了重新定义。函数进行了重新定义。函数进行了重新定义。函数进行了重新定义。5.3.2 公有继承的含义公有继承的含义 C+面向对象编程中一条重要的规则是:面向对象编程中一条重要的规则是:公有继承意味着公有继承意味着”是一个是一个”(isa)对于对于对于对于classD:classD:publicpublicBB;当写下类当写下类当写下类当写下类D D(”Derived”Derived”)从类从类从类从类B B(”Base”Base”)公有继承时,你实际上是在告诉编译器(以及读这公有继承时,你实际上是在告诉编译器(以
26、及读这公有继承时,你实际上是在告诉编译器(以及读这公有继承时,你实际上是在告诉编译器(以及读这段代码的人):类型段代码的人):类型段代码的人):类型段代码的人):类型D D的每一个对象也是类型的每一个对象也是类型的每一个对象也是类型的每一个对象也是类型B B的一的一的一的一个对象,但反之不成立;个对象,但反之不成立;个对象,但反之不成立;个对象,但反之不成立;也就是说,也就是说,也就是说,也就是说,B B表示一个比表示一个比表示一个比表示一个比D D更更更更广泛广泛广泛广泛的概念,的概念,的概念,的概念,D D表表表表示一个比示一个比示一个比示一个比B B更更更更特定特定特定特定概念;你是在声
27、明:任何可以使概念;你是在声明:任何可以使概念;你是在声明:任何可以使概念;你是在声明:任何可以使用类型用类型用类型用类型B B的对象的地方,类型的对象的地方,类型的对象的地方,类型的对象的地方,类型D D的对象也可以使用,的对象也可以使用,的对象也可以使用,的对象也可以使用,因为每个类型因为每个类型因为每个类型因为每个类型D D的对象是一个类型的对象是一个类型的对象是一个类型的对象是一个类型B B的对象。相反,的对象。相反,的对象。相反,的对象。相反,如果需要一个类型如果需要一个类型如果需要一个类型如果需要一个类型D D的对象,类型的对象,类型的对象,类型的对象,类型B B的对象就不行:的对
28、象就不行:的对象就不行:的对象就不行:每个每个每个每个DD是一个是一个是一个是一个B B,但反之不成立。但反之不成立。但反之不成立。但反之不成立。看这个例子:看这个例子:看这个例子:看这个例子:classPerson.;classPerson.;classStudentclassStudent:public:publicPersonPerson.;.;从日常经验中我们知道,每个学生是人,但从日常经验中我们知道,每个学生是人,但从日常经验中我们知道,每个学生是人,但从日常经验中我们知道,每个学生是人,但并非每个人是学生。这正是上面的层次结构所声并非每个人是学生。这正是上面的层次结构所声并非每个人
29、是学生。这正是上面的层次结构所声并非每个人是学生。这正是上面的层次结构所声明的。我们希望,任何对明的。我们希望,任何对明的。我们希望,任何对明的。我们希望,任何对“人人人人”成立的事实,成立的事实,成立的事实,成立的事实,如:都有生日,也对如:都有生日,也对如:都有生日,也对如:都有生日,也对“学生学生学生学生”成立;但我们不成立;但我们不成立;但我们不成立;但我们不希望,任何对希望,任何对希望,任何对希望,任何对“学生学生学生学生”成立的事实,成立的事实,成立的事实,成立的事实,如:都在如:都在如:都在如:都在某一学校上学,也对某一学校上学,也对某一学校上学,也对某一学校上学,也对 人人人人
30、 成立。人的概念比学成立。人的概念比学成立。人的概念比学成立。人的概念比学生的概念更广泛;学生是一种特定类型的人。生的概念更广泛;学生是一种特定类型的人。生的概念更广泛;学生是一种特定类型的人。生的概念更广泛;学生是一种特定类型的人。在在在在C+C+中,任何一个其参数为中,任何一个其参数为中,任何一个其参数为中,任何一个其参数为PersonPerson类类类类型的函数(或型的函数(或型的函数(或型的函数(或PersonPerson的指针或的指针或的指针或的指针或PersonPerson的引的引的引的引用)可以实际取一个用)可以实际取一个用)可以实际取一个用)可以实际取一个StudentStud
31、ent对象(或对象(或对象(或对象(或StudentStudent的指针或的指针或的指针或的指针或StudentStudent的引用)的引用)的引用)的引用)例:例:例:例:voidvoiddance(constdance(const PersonPerson&p);&p);/任何人可以跳舞任何人可以跳舞任何人可以跳舞任何人可以跳舞voidvoidstudy(conststudy(const StudentStudent&s);&s);/只有学生才学习只有学生才学习只有学生才学习只有学生才学习Personp;Personp;/p/p是一个人是一个人是一个人是一个人Students;/sStud
32、ents;/s是一个学生是一个学生是一个学生是一个学生dance(pdance(p);/);/正确,正确,正确,正确,p p是一个人是一个人是一个人是一个人dance(sdance(s);/);/正确,正确,正确,正确,s s是一个学生,是一个学生,是一个学生,是一个学生,/一个学生一个学生一个学生一个学生 是一个是一个是一个是一个 人人人人study(sstudy(s);/);/正确正确正确正确study(pstudy(p);/);/错误错误错误错误!p p不是学生不是学生不是学生不是学生5.3.2 派生类对象的构造派生类对象的构造 派生类的对象包含一个基类的子对象,因此一派生类的对象包含一
33、个基类的子对象,因此一派生类的对象包含一个基类的子对象,因此一派生类的对象包含一个基类的子对象,因此一个派生类的对象被创建的同时,一个基类的子对象应个派生类的对象被创建的同时,一个基类的子对象应个派生类的对象被创建的同时,一个基类的子对象应个派生类的对象被创建的同时,一个基类的子对象应该也被创建了,那么基类子对象是如何构造的呢?根该也被创建了,那么基类子对象是如何构造的呢?根该也被创建了,那么基类子对象是如何构造的呢?根该也被创建了,那么基类子对象是如何构造的呢?根据类的机制,基类的子对象应该通过基类的构造函数据类的机制,基类的子对象应该通过基类的构造函数据类的机制,基类的子对象应该通过基类的
34、构造函数据类的机制,基类的子对象应该通过基类的构造函数来完成构造。这样的话基类和派生类的构造函数负责来完成构造。这样的话基类和派生类的构造函数负责来完成构造。这样的话基类和派生类的构造函数负责来完成构造。这样的话基类和派生类的构造函数负责各自对象的构造,各自对象的构造,各自对象的构造,各自对象的构造,分工明确分工明确分工明确分工明确。例例 5-3 定义派生类构造函数和析构函数定义派生类构造函数和析构函数#include#include#include#include usingnamespacestd;usingnamespacestd;classPersonclassPersonprivat
35、e:private:charName20;charName20;intintAge;Age;charSex;charSex;/./.public:public:Person()Person()coutcout调用调用调用调用PersonPerson类的默认构造函数类的默认构造函数类的默认构造函数类的默认构造函数endlendl;strcpy(Name,Nostrcpy(Name,NoName);Name);Age=0;Age=0;Sex=M;Sex=M;Person(charPerson(char*pName,intpName,int pAge,charpAge,char pSexpSex)c
36、outcout调用调用调用调用PersonPerson类的构造函数类的构造函数类的构造函数类的构造函数endlendl;strcpy(Name,pNamestrcpy(Name,pName););Age=Age=pAgepAge;Sex=Sex=pSexpSex;Person()Person()coutcout调用调用调用调用PersonPerson类的析构函数类的析构函数类的析构函数类的析构函数endlendl;voidDisplay()voidDisplay()coutcoutName:NameName:Name,Age:Age,Age:Age,Sex:Sex,Sex:Sexendlend
37、l;classStudent:publicPersonclassStudent:publicPerson protected:protected:charMajor40;charMajor40;unsignedunsignedintint IdNumberIdNumber;unsignedunsignedintintLevel;Level;public:public:/-/-默认构造函数默认构造函数默认构造函数默认构造函数-Student()Student()coutcout调用调用调用调用StudentStudent类的默认构造函数类的默认构造函数类的默认构造函数类的默认构造函数endlen
38、dl;Major0=0;Major0=0;IdNumberIdNumber=0;=0;Level=0;Level=0;/-/-通过基类的带参构造函数构造基类的子对象(自定义通过基类的带参构造函数构造基类的子对象(自定义通过基类的带参构造函数构造基类的子对象(自定义通过基类的带参构造函数构造基类的子对象(自定义方式构造)方式构造)方式构造)方式构造)-Student(charStudent(char*pName,intpName,int pAgepAge,char,charpSexpSex,char*,char*pMajorpMajor,unsigned,unsignedintint pIdNu
39、mberpIdNumber,unsignedunsignedintint pLevelpLevel):PersonPerson(pName,pAge,pSex(pName,pAge,pSex)coutcout调用调用调用调用StudentStudent类的构造函数类的构造函数类的构造函数类的构造函数endlendl;strcpy(Major,pMajorstrcpy(Major,pMajor););IdNumberIdNumber=pIdNumberpIdNumber;Level=Level=pLevelpLevel;/-/-通过派生类的拷贝构造函数方式构造通过派生类的拷贝构造函数方式构造通过
40、派生类的拷贝构造函数方式构造通过派生类的拷贝构造函数方式构造-Student(constStudent(const Student&student)Student&student):Person:Person(student(student)coutcout调用调用调用调用StudentStudent类的拷贝构造函数类的拷贝构造函数类的拷贝构造函数类的拷贝构造函数endlendl;strcpy(Major,student.Majorstrcpy(Major,student.Major););IdNumberIdNumber=student.IdNumberstudent.IdNumber;Le
41、vel=Level=student.Levelstudent.Level;Student()Student()coutcout调用调用调用调用StudentStudent类的析构函数类的析构函数类的析构函数类的析构函数endlendl;voidDisplay()voidDisplay()Person:DisplayPerson:Display();();coutcout,IdNumberIdNumber:IdNumberIdNumber,Major:Major,Major:Major,Level:Level,Level:Levelendlendl;voidmain()voidmain()Per
42、sonPersonper(Zhangper(ZhangHong,20,F);Hong,20,F);Studentstu1;Studentstu1;Studentstu2(WangLei,21,M,Computer,1000,2);Studentstu2(WangLei,21,M,Computer,1000,2);Studentstu3(stu2);Studentstu3(stu2);coutcout人的信息:人的信息:人的信息:人的信息:n;n;per.Display();per.Display();coutendl;coutendl;coutcout第一个学生的信息:第一个学生的信息:第一个
43、学生的信息:第一个学生的信息:n;n;stu1.Display();stu1.Display();coutcout第二个学生的信息:第二个学生的信息:第二个学生的信息:第二个学生的信息:n;n;stu2.Display();stu2.Display();coutcout第三个学生的信息:第三个学生的信息:第三个学生的信息:第三个学生的信息:n;n;stu3.Display();stu3.Display();派生类对象的构造方式派生类对象的构造方式 1.1.通过默认构造函数进行构造通过默认构造函数进行构造通过默认构造函数进行构造通过默认构造函数进行构造语句语句语句语句Studentstu1;St
44、udentstu1;中,对象中,对象中,对象中,对象stu1stu1通过通过通过通过StudentStudent的默认构造函数进行构造,它的基类子对的默认构造函数进行构造,它的基类子对的默认构造函数进行构造,它的基类子对的默认构造函数进行构造,它的基类子对象通过基类的默认构造函数进行构造,通过程序的运象通过基类的默认构造函数进行构造,通过程序的运象通过基类的默认构造函数进行构造,通过程序的运象通过基类的默认构造函数进行构造,通过程序的运行结果可以看出来构造函数的调用次序是行结果可以看出来构造函数的调用次序是行结果可以看出来构造函数的调用次序是行结果可以看出来构造函数的调用次序是先调用基类先调用
45、基类先调用基类先调用基类的默认构造函数,再调用派生类的默认构造函数。的默认构造函数,再调用派生类的默认构造函数。的默认构造函数,再调用派生类的默认构造函数。的默认构造函数,再调用派生类的默认构造函数。2.2.通过用户自定义的构造函数进行构造通过用户自定义的构造函数进行构造通过用户自定义的构造函数进行构造通过用户自定义的构造函数进行构造语句语句语句语句Studentstu2(WangLei,21,M,Studentstu2(WangLei,21,M,Computer,1000,2);Computer,1000,2);中,对象中,对象中,对象中,对象stu2stu2通过通过通过通过StudentS
46、tudent的带的带的带的带参构造函数进行构造,通过构造函数的参数来完成基类子对参构造函数进行构造,通过构造函数的参数来完成基类子对参构造函数进行构造,通过构造函数的参数来完成基类子对参构造函数进行构造,通过构造函数的参数来完成基类子对象的构造,对基类子对象的构造方式类似于成员对象的构造象的构造,对基类子对象的构造方式类似于成员对象的构造象的构造,对基类子对象的构造方式类似于成员对象的构造象的构造,对基类子对象的构造方式类似于成员对象的构造方式,如下面的形式:方式,如下面的形式:方式,如下面的形式:方式,如下面的形式:Student(charStudent(char*pName,intpNam
47、e,int pAgepAge,char,charpSexpSex,char*char*pMajorpMajor,unsigned,unsignedintint pIdNumberpIdNumber,unsigned,unsignedintpLevelintpLevel):Person(pName,pAge,pSexPerson(pName,pAge,pSex)/./.在初始化成员列表中对基类的子对象进行构造。在初始化成员列表中对基类的子对象进行构造。在初始化成员列表中对基类的子对象进行构造。在初始化成员列表中对基类的子对象进行构造。3.3.通过拷贝构造函数进行构造通过拷贝构造函数进行构造通过拷
48、贝构造函数进行构造通过拷贝构造函数进行构造语句语句语句语句studentstu3(stu2);studentstu3(stu2);中,对象中,对象中,对象中,对象sut3sut3通过通过通过通过StudentStudent的拷贝构造函数进行构造,如果基类中有自定义的的拷贝构造函数进行构造,如果基类中有自定义的的拷贝构造函数进行构造,如果基类中有自定义的的拷贝构造函数进行构造,如果基类中有自定义的拷贝构造函数,那么基类子对象就通过它进行构造,否则通拷贝构造函数,那么基类子对象就通过它进行构造,否则通拷贝构造函数,那么基类子对象就通过它进行构造,否则通拷贝构造函数,那么基类子对象就通过它进行构造,
49、否则通过默认的拷贝构造函数进行构造,在本例中,过默认的拷贝构造函数进行构造,在本例中,过默认的拷贝构造函数进行构造,在本例中,过默认的拷贝构造函数进行构造,在本例中,PersonPerson类并未类并未类并未类并未提供默认的拷贝构造函数,因此程序的运行结果中也没有相提供默认的拷贝构造函数,因此程序的运行结果中也没有相提供默认的拷贝构造函数,因此程序的运行结果中也没有相提供默认的拷贝构造函数,因此程序的运行结果中也没有相关信息的输出。关信息的输出。关信息的输出。关信息的输出。当派生类对象的生命期结束时,如果派生类和基类的析当派生类对象的生命期结束时,如果派生类和基类的析当派生类对象的生命期结束时
50、,如果派生类和基类的析当派生类对象的生命期结束时,如果派生类和基类的析构函数都被定义了,则它们会被自动调用。析构函数的调用构函数都被定义了,则它们会被自动调用。析构函数的调用构函数都被定义了,则它们会被自动调用。析构函数的调用构函数都被定义了,则它们会被自动调用。析构函数的调用顺序是先派生类的析构函数,然后再基类的子对象的析构函顺序是先派生类的析构函数,然后再基类的子对象的析构函顺序是先派生类的析构函数,然后再基类的子对象的析构函顺序是先派生类的析构函数,然后再基类的子对象的析构函数数数数。从本例的程序运行结果可以看出来,派生类对象析构函。从本例的程序运行结果可以看出来,派生类对象析构函。从本