构造和析构函数_第1页
构造和析构函数_第2页
构造和析构函数_第3页
构造和析构函数_第4页
构造和析构函数_第5页
已阅读5页,还剩36页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第五章 构造和析构函数 构造和析构函数classStudent{public:Student();//构造函数的声明;系统约定与类同名,自动调用,没有返回值,可以重载~Student();//析构函数的声明;没有参数,没有返回值,不可以重载;对象生命期结束时由系统自动调用protected: char*name;intage;};Student::Student(){cout<<"构造"<<endl;age=5;}Student::~Student(){cout<<“析构,对象结束了"<<endl;}intmain(){ Studenta;Studentb;return0;}析构函数的调用顺序和对象构造的顺序相反析构函数不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作。还可以用来执行用户希望在对象生命期结束时所执行的任何操作。2

C++标准库--stringstringname;自动处理空间的占用问题。可以用=进行赋值操作,==进行比较,+做串联.使用时#include<string>

stringstr1,str2=“abcd”;

str1=str2;

str2=str1+”123”;

cout<<str2<<""<<str2.length();由C++字符串得到对应的C_string的方法是使用data()、c_str()chars[20];strcpy(s,str1.data());strcpy(s,str2.c_str()); 带参数的构造函数

classStudent{ public:

Student(stringpName,inti,floatj){

cout<<"构造学生"<<pName<<endl;

name=pName;

semesHours=i;

gpa=j;

}

~Student()

{cout<<"析构"<<name<<endl;} private:

stringname;intsemesHours;floatgpa;

};

voidf(){Studentt("Tom",17,90);}

intmain(){

Studentss("Jenny",20,80.5);

f();

return0;

} 构造和析构函数classA{public: ints;};Aa1;对于没有显性构造函数的类系统都自动提供一个默认构造函数

A(){}用户没有定义析构函数,编译器自动生成一个析构函数。

~A(){} 构造函数重载classStudent{

public:

Student(stringpName){

cout<<"姓名"<<pName<<endl;

name=pName;

}

Student(stringpName,inti){

cout<<“姓名学时"<<endl;

name=pName;

semesHours=i;

}

Student(){}//自定义无参构造函数将替代缺省构造函数的存在

private:

stringname;intsemesHours;

};

intmain(){

Studenttt("Tom",60);Studentss("Jenny");

Studentf;

return0;

}如果手工定义了任何的构造函数,系统不再提供默认的无参构造函数。 默认值构造函数classStudent{public:

Student(stringpName=“”,inti=0){

cout<<“姓名学时"<<endl;

name=pName;

semesHours=i;

}protected:

stringname;intsemesHours;};intmain(){

Studenttt("Tom",60);Studentss("Jenny");

Studentf;//不错误return0;}无名对象(一次性对象):Student("Jane");一般作为实参,用在创建后不需要反复使用的场合 构造函数构造函数是特殊的类成员函数。C++规定与类同名的成员函数是构造函数,在该类的对象创建时,自动被调用。构造函数负责对象的初始化可拥有多个参数。可以重载。构造函数不返回具体的值,不指定函数的返回类型。可内置定义,也可以在类外定义。通常是Public的 析构函数析构函数也是一个特殊的成员函数;作用与构造函数相反;在对象的生命期结束时自动被调用。名字是类名前加一个~;不返回任何值;没有函数类型,没有函数参数,因此不能被重载。一个类可以由多个构造函数,只能有一个析构函数。可内置定义,也可以在类外定义。用于清理和释放资源的工作。通常是Public的 练习题判断对错,错误写出原因:1、使用struct定义的类中默认的访问权限是private的2、this不能被非成员函数访问3、任何情况下private权限的内容不能被类外访问4、引用破坏了函数的封装性5、内联函数的作用是提高系统的效率6、不同类的成员函数也可以重载7、参数类型、函数返回类型可以作为函数重载的依据 组合类组合:是指结构和类的声明嵌入结构变量和对象作为其成员的现象嵌入的对象成员称为成员对象(类成员)包容这个成员对象的类称为组合类 组合类创建classStudent{public:

Student(){

cout<<"constructingstudent.\n";

semesHours=100;}~Student(){cout<<“~Student\n”;}protected:

intsemesHours;};classTeacher{public:

Teacher(){cout<<"constructingteacher.\n";}

~Teacher(){cout<<“~Teacher\n”;}private:

charname[20];};classTutorPair{public:

TutorPair(){

cout<<"constructingtutorpair.\n";

noMeetings=0;

}

~TutorPair(){cout<<“~TutorPair\n”;}protected:

Studentstudent;

Teacherteacher;

intnoMeetings;};intmain(){

TutorPairtp;

cout<<"backinmain.\n";return0;} 组合类对象的初始化困惑classStudentID{public:

StudentID(intid=0){

value=id;

}

~StudentID(){}protected:

intvalue;};classStudent{public:

Student(stringpName="noName",intssID=0){name=pName;

}private:

stringname;

StudentIDid;};intmain(){

Students("Randy",9818);

return0;} 组合类的构造函数classStudentID{public:

StudentID(intid=0){

value=id;

}

~StudentID(){}protected:

intvalue;};classStudent{public:

Student(stringpName="noName",intssID=0):id(ssID){name=pName;

}private:

stringname;

StudentIDid;};intmain(){

Students("Randy",9818);

return0;}冒号语法:用冒号引出构造函数的调用表(初始化列表),用构造参数列表中说明的参数去调用构造函数 例子classStudent{public:

Student(inti){

cout<<"constructingstudent.\n";

semesHours=i;}~Student(){cout<<“~Student\n”;}protected:

intsemesHours;};classTeacher{public:

Teacher(stringp){

cout<<"constructingteacher.\n"; name=p; }

~Teacher(){cout<<“~Teacher\n”;}private: stringname;};classTutorPair{public:

TutorPair(inti,intj,stringp): teacher(p),student(j){

cout<<"constructingtutorpair.\n";

noMeetings=i;

}

~TutorPair(){cout<<“~TutorPair\n”;}protected:

Studentstudent;

Teacherteacher;

intnoMeetings;};intmain(){

TutorPairtp(5,20,"Tim");

cout<<"backinmain.\n";return0;} 构造函数初始化常数据成员和引用成员 classStudent{public:

Student(ints,int&k):i(s),j(k)

{}//不可以直接赋值

voidp(){cout<<j<<endl;}protected:

constinti;

int&j;};intmain(){

intc=123;

Students(9818,c);

s.p();

return0;} 对象构造顺序局部和静态局部对象(文件作用域)以文本定义顺序为顺序,(类成员属于此种情况)静态对象在首次定义时构造一次;程序结束析构全局对象在main之前构造;程序结束时析构全局对象如果分布在不同文件中,则构造顺序随机 例子classA{public: A(intk){s=k;cout<<k<<"Aisconstructing\n";}; ~A(){cout<<s<<"~A\n";} ints;};intmain(){

cout<<"mainisrunning\n";

As(1);voidf();f();f();

return0;}voidf(){

cout<<"fisrunning\n";

As(2);

staticAt(3);}At(4); 练习重写Rectangle,将坐标抽象为Point类,通过冒号语法对Rectangle中的Point类进行初始化 为对象申请动态空间Malloc和对应的free函数不能调用构造函数和析构函数,这破坏了:空间分配、初始化的功能。所以引入了new和delete。因为空间不确定才使用堆空间函数内部的申请空间要及时释放,否则容易造成内存泄漏 malloc\newclassaa{public:aa(inta=1){id=a;cout<<"构造"<<endl;}intid;~aa(){cout<<“aais析构.”<<endl;}};intmain(){

aa*p=newaa(9);

cout<<p->id;

aa*q=(aa*)malloc(sizeof(aa));

cout<<q->id;//随机数,表明构造函数未调用

deletep;

free(q);//析构函数未调用

return0;} 例子classaa{public:aa(inta=1){id=a;}intid;};aa&m(){

aa*p=newaa(9);

return(*p);}intmain(){

aa&s=m();

cout<<s.id;//结果为9表明没有释放

return0;} 例子classaa{public:aa(inta=1){id=a;}intid;};aa&m(){

aa*p=newaa(9);

deletep;//释放后不应该再返回

return(*p);}intmain(){

aa&s=m();

cout<<s.id;//结果为随机数表明被释放

return0;} 析构函数的需要性classaa{public:aa(inta=9){age=newint[a];}

~aa(){delete[]age;}

int*age;};intmain(){

aa*s=newaa;

s->age[0]=20;

int*t=s->age;

deletes;

cout<<t[0];

return0;} 对象数组classStudent{public:

Student(){cin>>value;}

~Student(){cout<<value<<endl;}protected:

intvalue;};intmain(){

Student*p=newStudent[5];

cout<<“DeleteBegin”<<endl;

delete[]p;

return0;}对象数组不能通过参数传递初始化。要么默认构造函数,要么构造函数有默认参数Studenta[10](20);//错误

建立动态数组intnextStudentID=1;classStudentID{public:StudentID(){ value=nextStudentID++;}~StudentID(){--nextStudentID;}protected:intvalue;};classStudent{public:Student(stringpName="noName"){name=pName;}protected:stringname;StudentIDid;};intmain(){ inti,

j; stringtemp; cin>>i; Student**p=newStudent*[

i

]; for(j=0;j<i;j++){ cin>>temp; p[j]=newStudent(temp); cout<<nextStudentID;

}

for(j=i-1;j>=0;j--)

deletep[j]; delete[]p; cout<<nextStudentID;

return0;} 例子

inti;inta[i];//error

inti;

cin>>i;

int*p=newint[i];delete[]p; 对象的赋值classStudent{ stringname;intsemesHours;public: Student(stringpName=“”,inti=0){

name=pName;semesHours=I;

}};Studenta("jenny",50);Studentb;b=a;一个已知对象赋值给另一个已知对象,通过对赋值运算符的重载实现的

Student&operator=(constStudent&rValue){

name=rV;

semesHours=rValue.semesHours;

return*this;} 对象的拷贝用一个已知对象构造(初始化)一个新对象。 Students1(“Jenny”);

Students2=s1;即Students2(s1);

Studentfn(Students){Studentk;//.......;returnk}//window下 intmain(){ Studentm,n;

n=fn(m);return0; }拷贝构造函数

Student(constStudent&s){

name=;semesHours=s.semesHours;

}

例子-练习,调用哪个函数classStudent{public: Student(intk):i(k){}

Student(){} voidp(){cout<<i<<endl;}protected: inti;};intmain(){

Students(9818);

s.p(); Studentt(s); t.p();

Studentm;

m=t;

m.p();

return0;} 重写拷贝构造函数classStudent{public: Student(intk):i(k){}

Student(){} voidp(){cout<<i<<endl;}

Student(Studentconst&m){i=m.i*(-1);}//重写拷贝构造函数protected: inti;};intmain(){

Students(9818);s.p();Studentt(s);t.p(); Studentk=s;k.p(); Student*p=newStudent(s); p->p(); Studentm;m=s; m.p();return0;} 浅拷贝classaa{public:aa(){ f=newchar[10]; }~aa(){delete[]f;}char*f;};intmain(){ aap; strcpy(p.f,"Computer"); cout<<p.f<<endl; aaq(p);//aaq=p; cout<<q.f<<endl; strcpy(p.f,"Software"); cout<<q.f<<p.f<<endl;

return0;}创建q时,对象p被复制给了q,但资源未复制,使得p和q指向同一个资源,这称为浅拷贝同一个指针执行两遍delete操作,会发生什么?灾难,可能会破坏该堆及自由内存表 深拷贝classaa{public: aa(){f=newchar[10];} aa(aaconst&s){

f=newchar[10];strcpy(f,s.f);} ~aa(){delete[]f;} char*f;};intmain(){ aap; strcpy(p.f,"Computer"); cout<<p.f<<endl; aaq(p); cout<<q.f<<endl; strcpy(p.f,”Software”); cout<<p.f<<q.f<<endl; return0;} 例子-练习classStudent{public: Student(inti){value=i;cout<<"Student"<<value<<endl;} ~Student(){cout<<"~Student"<<value<<endl;}protected: intvalue;};intmain(){ Student(9); Student*p=&Student(8); Student&q=Student(7); Studenti(6); i=Student(5);

return0;} 类型转换classaa{public:aa(inta=1){id=a;cout<<"构造"<<endl;}aa(constaa&s){id=s.id;cout<<"拷贝"<<endl;}int&Getid(){return(id);}private:intid;};intmain(){ aam;//“构造” aan(m);//“拷贝” aao=m;//“拷贝”和aao(m)等价

aas=9;//“构造”和aas(9)等价 aat;//“构造”

t=9;//“构造”、赋值运算

return0;} 类型转换classaa{public:aa(inta=1){id=a;}char*p;intid;};voidm(aaa){cout<<a.id<<endl;}intmain(){m(9);//相当于m(aa(9));return0;}如果存在m(int)的函数则优先匹配 类型转换classaa{public:aa(inta=1){id=a;}intid;};classbb{public:bb(inta=2){id=a;}intid;};voidm(aaa){cout<<a.id<<endl;}voidm(bba){cout<<a.id<<endl;}intmain(){

m(9);//存在二义性;

return0;} 类型转换classHighWorker{floatincome;public:HighWorker(floata=2000.0){income=a;}floatGetincome(){return(income);}};classWorker{floatincome;public:Worker(fl

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论