C语言程序设计课件:类与对象_第1页
C语言程序设计课件:类与对象_第2页
C语言程序设计课件:类与对象_第3页
C语言程序设计课件:类与对象_第4页
C语言程序设计课件:类与对象_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

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

文档简介

类与对象C语言程序设计目录content类的实例化——对象1类的构造函数和析构函数2new和delete3this指针4拷贝构造函数5运算符重载6类的特殊成员7对象成员8对象数组与对象指针9友元0112.1类的实例化——对象

面向对象程序设计的基本单元是对象,通过对诸多同类型的对象进行抽象得到class类的声明,再使用该class类类型创建多个不同的对象,具有class类型的变量被称作该类的对象,又叫该类的实例。StudentmyStudent;例如myStudent对象的内存映像

数据空间代码空间使用运算符“.”来访问对象的成员12.1类的实例化——对象例Studenta,b;a.registerStudent(“Tom”,”123456”,20);b.registerStudent(“Jerry”,”123457”,20);a.show();b.show();既然所有对象共享同一个代码空间,系统是如何区分某个成员函数代码到底在处理哪个对象的数据呢?(this指针见12.4)12.2

类的构造函数和析构函数构造函数:在创建对象时,编译器自动调用类的构造函数,自动地进行数据成员的初始化。析构函数:类对象退出它的作用域时,编译器会自动调用析构函数来处理善后工作。优点:1)简化对象的初始化2)减少人为失误造成的设计漏洞,如:内存泄漏classStudent{private:charname[20];charid[15];intage;public:Student(constchar*n,constchar*i,inta);voidshow();};Student::Student(constchar*n,constchar*i,inta){strcpy(name,n);strcpy(id,i);age=a;}12.2.1构造函数下面为Student类定义一个构造函数Student(),用它来初始化数据成员。1)构造函数与类同名,不能为其制定任何返回类型2)当对象被创建时,构造函数被自动调用。intmain(){StudentmyStudent(“Tom”,“123456”,20);//创建Student类的对象myStudentreturn0;}12.2.2

重载构造函数和缺省构造函数例classmyClass{private:inta,b;public:myClass();myClass(inti,intj);voidshow();};myClass::myClass(){cout<<“执行myClass()”<<endl;a=0,b=0;}myClass::myClass(inti,intj){cout<<“执行myClass(int,int)”<<endl;a=i,b=j;}intmain(){myClassob1;myClassob2(10,5);return0;}当执行语句myClassob1时,调用第一种不带参数的缺省构造函数,而当执行语句myClassob2(10,5)时,调用第二种带2个整型参数的重载构造函数12.2.2

重载构造函数和缺省构造函数几点说明:(1)定义对象ob1时语句为myClassob1;不能写成:myClassob1();(2)当我们没有为Student类定义任何构造函数时,编译器会自动为该类创建一个不带参数的构造函数,即缺省构造函数。且只能这样定义该类的对象:StudentmyStudent;(3)强烈建议让每个类都拥有一个不带参数的构造函数,即使这个构造函数为空。这样在使用对象数组和创建派生类对象时不会发生不必要的麻烦。(4)如果一个构造函数的所有参数均带有缺省值,那么这个构造函数本质上和缺省构造函数有等同的作用,原因在于调用它时可以不必传递任何参数。此时当然还可以再定义不带参数的构造函数了,但是如果在创建对象时采用了不传递任何参数的方式,因为会产生歧义,编译器将无法确定是调用定义了缺省值的构造函数,还是调用不带任何参数的构造函数,此时编译器将提示出错12.2.3析构函数每当撤销一个对象时,析构函数就会自动调用。撤销对象分为两种场景:对象在离开其作用域时,以及用new运算符创建的动态对象在使用delete运算符操作时。例如classmyClass{private:inta,b;public:myClass();~myClass();

…};

…myClass:~myClass(){cout<<“执行析构函数”<<endl;}析构函数voidmain(){myClassob;cout<<”main()函数运行结束!”<<endl;}运行情况如下:main()函数运行结束执行析构函数12.2.3析构函数几点说明:(1)析构函数必须和类同名,并且在函数名前面加上一个~字符;(2)析构函数不能带任何参数,因此,不能对析构函数进行重载;也不能为析构函数指定任何返回类型,即使void也不行;(3)每当对象撤销时,总要先自动执行析构函数。如果没有显式地定义类的析构函数,系统也会自动加上缺省析构函数,但函数体为空12.2.3析构函数例类Chunk的构造函数Chunk()动态分配一块大小为size的堆内存,析构函数负责释放这块堆内存classChunk{private:void*p;public:Chunk(unsignedintsize=0);~Chunk();};Chunk::Chunk(unsignedintsize){p=newchar[size];//分配一个char型的数组空间,该数组有size个元素}Chunk::~Chunk(){delete[]p;//释放分配的size个char型元素空间}12.2.3析构函数几点说明:(1)析构函数只负责回收以前在创建对象时在构造函数中分配的动态堆内存,以及在对象生存期间通过对象的其它成员函数分配的动态堆内存。而不是指类对象本身所占的内存空间。因为,析构函数本身代码就是对象的一部分,其占据对象一部分内存空间,本身代码的执行不能回收自身所占的内存空间。(2)调用构造函数和析构函数的时机:局部对象在程序执行到它的定义语句时创建,调用构造函数;在退出它的作用域时撤销该对象,调用析构函数;全局对象在程序执行主函数main之前创建,在整个程序执行结束时撤销;对于用new运算符动态创建的对象,当创建时调用构造函数,使用delete运算符释放该对象时调用析构函数。若不通过delete显式地释放动态对象,那么程序将不会自动释放该对象。12.3new和delete例voidmyfun(){int*pi=NULL;//通常指针未明确建立指向前,赋值NULL,处于“休息”态pi=newint;//注意对比:pi=(int*)malloc(sizeof(int));if(pi==NULL)//如果内存中没有足够的动态内存,则返回NULL指针{ cout<<“内存不足”<<endl; exit(1);}*pi=10;cout<<*pi<<endl;deletepi;//注意对比:free(pi);pi=NULL;//一旦释放空间,使用权交回系统,但pi的指向不变,成为//危险的“野指针”。为了安全,将赋值NULL,处于“休息”态}12.3new和delete几点说明:(1)new运算符可以动态分配一个数据空间,也可以动态分配数组空间。delete运算符与new运算符配合使用,用来释放已分配的内存空间。如果用new分配的是一个数组,那么最好用delete[]来释放;12.3new和delete(2)malloc和free等库函数和new和delete运算符的区别:a)由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。b)对于内部数据类型(比如:int)的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。c)为什么C++不把malloc/free淘汰出局呢?这是因为C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存。另外,malloc/free功能还有一好处,就是可以和realloc组合使用,在需要扩大内存块时不一定会导致内存移动;而用new/delete实现时只能用new[]-copy-delete[]操作序列完成,每次都会导致内存移动。(3)new/delete也可以用于创建和销毁对象。当使用new运算符创建动态对象后,使用delete运算符操作时会销毁对象,此时析构函数会自动调用。这是析构函数自动调用的第二种场景12.4this指针当成员函数被调用时,会有一个隐含的参数自动传递给该函数,这个隐含的参数是一个指向调用该成员函数对象的指针,叫做this指针。例classComplex{private:doublereal,imag;public:voidset(doubler,doublei);voidshow();Complexadd(Complex&c);};voidComplex::set(doubler,doublei){real=r,imag=i;}voidComplex::show(){cout<<“real=”<<real<<‘,’<<“imag=”<<imag<<endl;}ComplexComplex::add(Complex&c){Complextemp;temp.real=real+c.real;temp.imag=imag+c.imag;returntemp;}intmain(){Complexob1,ob2,sum;ob1.set(1,3.5);ob2.set(10.5,4);sum=ob1.add(ob2);sum.show();return0;}加法运算是在两个Complex对象之间进行,运算结果是第三个Complex对象。但是成员函数add却只有一个参数c,这是为什么呢?原来,成员函数add还有一个隐含的参数this,它是被自动传递给add函数的。this指针指向当前调用add函数的对象。相当于:ComplexComplex::add(Complex*constthis,Complex&c){Complextemp;temp.real=this->real+c.real;temp.imag=this->imag+c.imag;returntemp;}12.4this指针几点说明:(1)this指针是指向调用成员函数的对象指针,它的类型是:类名*constthis;由此可见,this指针是常量指针,在程序里不能直接给this赋值,但是可以给this指向的对象赋值:*this=…;(2)在成员函数中可以显式引用this指针;当成员函数的形参标识符与类的数据成员同名时,需要使用this指针“显式”地指明数据成员以示区分。但这种情况应尽量避免,以提高程序的可读性。12.5拷贝构造函数拷贝构造函数:对于同class类型的两个对象,可以他们之间使用拷贝构造函数相直接整体赋值例classComplex{private:doublereal,imag;public:Complex(constdoubler=0,constdoubleii=0);voidShow();};Complex::Complex(constdoubler,constdoubleii){real=r,imag=ii;}voidComplex::Show(){cout<<“实部=”<real<<‘’<<“虚部=”<<imag<<endl;}intmain(){Complexob1(5.8,10.5);Complexob2(ob1); //调用缺省拷贝构造函数ob2.Show();return0;}程序运行结果:实部=5.8虚部=10.5

也可以直接利用赋值运算符:Complexob2=ob1;12.5this指针几点说明:(1)缺省拷贝构造函数是在类中没有拷贝构造函数时编译器自动加进类中,它负责实现“逐域”地拷贝对象的数据。(2)尽管拷贝构造函数和赋值运算符(=)都是把一个对象的数据拷贝到另一个同类型对象,但二者是有区别的:拷贝构造函数用来创建新对象并完成对该对象数据成员的初始化;而赋值运算符则是用来改变一个已有对象的值。12.5.2自定义拷贝构造函数类名([const]类名&参数名);一般形式classLocation{public:Location(intxx=0,intyy=0){X=xx;Y=yy;cout<<“Objectconstructed.”<<endl;}Location(Location&p);~Location(){cout<<X<<“,”<<Y<<“Objectdestroyed.”<<endl;}intGetX(){returnX;}intGetY(){returnY;}private:intX,Y;};Location::Location(Location&p){X=p.X;Y=p.Y;cout<<“Copy_constructorcalled.”<<endl;}main(){LocationA(1,2);LocationB(A); //自定义的拷贝构造函数被调用cout<<“B:”<<B.GetX()<<“,”<<B.GetY()<<endl;}例12.5.2自定义拷贝构造函数例

如果类不含指针类型的数据成员,那么缺省拷贝构造函数“逐域”地拷贝已存在的对象来初始化被创建的新对象是不会出错的。但如果类中包含指针类型的数据成员,则会产生运行错误。classMessage//类Message用来保存一个消息串{private:char*buffer;//数据成员buffer指向被保存的消息串public:Message(constchar*str);~Message();voidshow();};Message::Message(constchar*str){buffer=newchar[strlen(str)+1];//堆区内存的分配if(buffer!=0)strcpy(buffer,str);}Message::~Message(){delete[]buffer;//堆区内存的回收}intmain(){Messageob1(“Hello”);Messageob2(ob1);//产生运行错误return0;}12.5.2自定义拷贝构造函数由于这个缺省拷贝构造函数仅仅完成简单的“逐域”拷贝工作,这就是常说的“浅拷贝”。于是ob1.buffer和ob2.buffer指向同一块内存空间。

当撤销对象ob2时,执行析构函数,将释放ob2.buffer所指向的堆内存空间。接着系统又要撤销ob1,同样要执行一次析构函数,也要释放ob1.buffer所指向的堆内存空间。同一块内存空间被释放两次,导致运行错误。针对上述情况,应该定义自己的拷贝构造函数来实现“深拷贝”。12.6运算符重载C++中预定义的运算符操作对象只能是基本数据类型,对于许多用户自定义类型(例如类),也需要类似的运算操作。这时就必须在C++中重新定义这些运算符,运算符重载的实质是函数重载。<返回类型说明符>operator<运算符符号>(<参数表>){<函数体>}一般形式例创建对象常见的有下面几种方式:

myClassob1;//调用不带参数的构造函数myClassob2(ob1);//调用缺省拷贝构造函数或用户自定义拷贝构造函数myClassob3(3);//调用带整数类参数的构造函数myClassob4=ob1;//调用拷贝构造函数myClassob5;ob5=ob1;//调用缺省赋值运算符函数或自定义成员函数operator=myClassob6=3;//调用带整型参数的构造函数(1)赋值操作是在对象被创建完毕以后的时间段完成的,完成对象状态的修改;而初始化针对一个新对象,是在对象创建的阶段,完成对其最初状态的设置。(2)运算符重载后,可以按它的表达方式使用,但不能改变它们的优先级和要求的操作数数目。运算符被重载后,原有意义没有失去,只是定义了相对于一特定类的一个新运算符。运算符函数用成员函数重载时,必须是公有的。12.6运算符重载如果类没有自定义的重载赋值运算符函数,缺省赋值运算符函数和缺省拷贝构造函数一样,“逐域”拷贝对象中的每个数据成员,这样,当类中存在指针数据成员时就会存在和拷贝构造函数同样的弊端。例运算符重载函数classMessage{public:

…//略Message&operator=(Message&me);

…//略}Message&Message::operator=(Message&me){if(this==&me)return*this;//判断是否同一个对象delete[]buffer;buffer=newchar[strlen(me.buffer)+1];strcpy(buffer,me.buffer);return*this;}12.7类的特殊成员const可以修饰类的数据成员和成员函数,分别称作const数据成员、const成员函数。#include<iostream.h>classmyClass{private:constintci; //常量数据成员int&ref; //引用数据成员public:myClass(int&i):ci(10),ref(i)//冒号(:)后面的ci(10),ref(i)就是成员初始化列表{ }voidShow(){cout<<ci<<”,”<<ref<<endl;}};voidmain(){inta=10;myClassob(a);ob.Show();}定义const变量时必须给出初始值,但C++规定,不允许在类的声明中为类的常量和引用数据成员提供初始值初始化的方式:成员初始化列表12.7.1.1const数据成员类名::类名(参数表):数据成员名(值),数据成员名(值),…数据成员名(值){函数体}成员初始化列表的一般形式几点说明:1)成员初始化列表用于在创建对象的同时给对象数据成员赋初始值,成员初始化列表只能用在构造函数中。成员初始化列表必须写在构造函数的参数表和构造函数的函数体之间,且与参数表之间用冒号(:)隔开。2)如果构造函数定义在类的说明之外,成员初始化列表只能写在构造函数定义处的参数表和构造函数函数体之间。3)成员初始化列表的各项应用逗号隔开。成员初始化列表不仅可以给常量和引用数据成员初始化,而且可以给普通数据成员初始化。const成员函数12.7.1.2当我们不希望函数修改类的数据成员的值时,可以把该成员函数指定为const成员函数classmyClass{private:intvalue;int*ptr;public:…intGet()const//Get函数不能修改任何数据成员{returnvalue;}voidGood(inti)const //Good函数也不能修改任何数据成员{*ptr=i;//修改的是ptr指向的数据空间,该空间不是类的数据成员}};const应该放在成员函数参数表和函数体之间。如果成员函数在类的说明体外定义,在类的说明中该成员函数原型说明后也应加上const几点说明:1)const对象只能访问类的const成员函数,不能访问非const成员函数,对于const对象,程序不能修改它的任何数据成员。2)编译器会自动检查const成员函数,看它有没有修改该类的数据成员,若修改了,则给出编译错误信息。但const成员函数可以修改被mutable修饰的数据成员12.7.1.2const成员函数12.7.2静态成员

在数据成员或成员函数的前加static修饰符,称为静态数据成员和静态成员函数。静态成员是属于整个类的而不是某个对象,不会随对象的消失而消失。静态成员变量只存储一份,为所有对象共用、共享。intcount=0;classmyClass{private:intvalue;public:myClass(){value=0;count++;}~myClass(){count--;}};例#include<iostream.h>classmyClass{private:intvalue;public:staticintcount;//静态数据成员myClass(){value=0;count++;}~myClass(){count--;}};myClass不再是一个独立的类,而是一个依赖于全局变量count的类。静态数据成员12.7.2.1几点说明:1)静态数据成员是类的成员,遵从一般类的成员访问规则。2)当没有创建该类的任何对象时,静态数据成员仍然存在,在创建对象之前,我们通过类名myClass::count来访问静态数据成员。3)由于静态数据成员不属于特定的对象,因而不能使用构造函数和析构函数进行初始化和撤销。4)静态数据成员必须在全局区定义,注意在定义时不要加上static。静态成员函数12.7.2.2在类之外能通过myClass::count,访问count,这不符合类的封装性,应将count说明为静态私有数据成员,定义静态成员函数GetCount()仅供类的对象来访问count,这样也能保持静态成员不依赖于特定对象的存在而存在的本质。#include<iostream.h>calssPoint{private:staticintcount;public:…staticintGetCount(){returncount;}};intPoint::count=0;//仍然需要在全局区定义intmain(){…}例12.7.2.2静态成员函数几点说明:1)在类的说明中,对静态成员函数的原型,必须要有static,以表示为静态成员函数。静态成员函数也可以在类外定义,在定义时省略static关键字。2)当对象被创建后,也可以通过对象名来访问静态成员函数,但要“显式”地传递对象指针,才能访问对象的成员(不推荐这种用法)。3)静态成员函数中只能直接访问类的静态数据成员,不能直接访问类的非静态数据成员。4)由于不传递this指针,从本质上看,静态成员函数不能算是严格的类的成员函数。静态成员函数可以在没有声明类的任何实例(对象)之前就被执行。12.8对象成员在类中可以说明具有类类型的数据成员,即对象成员#include<iostream.h>#include<string.h>classstudentID{intvalue;public:studentID(intd=0){value=d;cout<<"Assigningstudentid"<<value<<endl;};~studentID(){cout<<"Destructingid"<<value<<endl;};};classstudent{charname[20];studentIDid;public:student(char*pname="noname",intssID=0):id(ssID){cout<<"Constructingstudent"<<pname<<endl;strncpy(name,pname,sizeof(name));};~student{cout<<"Destructingstudent"<<pname<<endl;};};voidmain(){students(“Tom",9818);}程序运行结果:Assigningstudentid9818ConstructingstudentTomDestructingstudentTomDestructingid981812.8对象成员几点说明:1)类的构造函数应在其初始化列表里调用对象成员类的构造函数。也就是说,要想初始化对象成员id,必须在类Student构造函数的成员初始化列表中进行。2)如果有多个对象成员需要初始化,则用逗号隔开各项。对象成员的初始化顺序可以随意安排,但编译器对对象成员的构造函数的调用顺序取决于对象成员在类中说明的顺序,与它们在成员初始化列表中给出的顺序无关。3)析构函数的调用顺序恰好和构造函数的调用顺序相反,具有唯一性。4)创建对象s时,编译器先执行对象成员的构造函数体为对象进行初始化,创建完所有的对象成员之后,才执行这个拥有对象成员的对象的构造函数体,以初始化该对象的其他成员。12.9对象数组与对象指针#include<iostream.h>classmyClass{private:intvalue;public:myClass(){value=0;}myClass(intv){value=v;}voidSet(intv){value=v;}voidShow(){cout<<value<<endl;}};intmain(){myClassarr[3];intii;for(ii=0;ii<3;ii++)arr[ii].Show();cout<<endl;for(ii=0;ii<3;ii++){arr[ii].Set(ii);arr[ii].Show();}return0;}对象数组程序将自动调用不带参数的构造函数myClass()来创建三个数组元素,对象数组的初始化1)myClassarr[3]={0,1,2};调用带一个整型参数的构造函数myClass(int)2)myClassarr[3]={myClass(0),myClass(1),myClass(2)};12.9.1对象数组几点说明:1)基本类型的数组不提供初值,系统会给所有元素清0,但对象数组如果不给初始值,对象元素的数据成员不一定清0。系统会调用不带参数的构造函数(可能是缺省的,也可能是用户自定义的)来创建对象元素。2)建议自定义不带参数的构造函数12.9.2对象与指针classmyClass{private:intvalue;public:myClass(intv){value=v;}voidShow(){cout<<value<<endl;}};intmain(){myClassob(10);myClass*ptr=&ob;//ptr指向对象obptr->Show();//利用成员访问运算符‘->’访问所指对象的成员函数myClassarr[3]={0,1,2};ptr=arr;for(intii=0;ii<3;ii++){ptr->Show();ptr++;}return0;}对象指针指向对象数组的指针ptr,如果通过ptr++或ptr--移动来改变指向关系,并不是指针值简单的增减1,而是增减一个对象所占的字节数。12.9.2对象与指针classmyClass{private:intvalue;public:myClass(intv){value=v;}myClass(){value=0;}};voidmain(){myClass*ptr=NULL;ptr=newmyClass(1);//调用构造函数myClass(int)创建动态对象if(ptr==NULL){ cout<<”内存不足!”<<endl; exit(1);}myClass*arr=NULL;arr=newmyClass[5];if(arr==NULL){cout<<”内存不足!”<<endl; exit(1);}delete[]arr;deleteptr;}动态对象数组几点说明:1)动态对象数组与前面通过数组定义得到的对象数组的主要区别是:分配的内存空间不在同一个内存区,通过定义的对象数组是分配在栈空间或者全局数据区,而动态对象数组是在堆空间里分配内存;2)不能丢失ptr指针,否则,将无法引用动态对象数组,更严重的是,将造成所谓的“内存泄漏”。3)用new分配动态对象数组时,不能指定任何初始值。下面的语句存在语法错误:arr=newmyClass[5](1);针对动态对象数组,只能调用不带参数的构造函数来创建每一个动态对象元素。因此,强烈建议在类的设计中一定要提供自定义的不带参数的构造函数。12.9.2对象与指针12.10友元

类具备封装和信息隐藏的特性,只有类的成员函数才能访问类的私有成员。在某些情况下,特别是在对成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。因此,C++中提出友元的概念,友元能够扩大私有成员的访问范围到全局函数或其他类的某成员函数,甚至扩大到其他类整个域。友员给予别的类或非成员函数访问私有成员的权利,使用友员目的是基于程序的运行效率。类的友元分为友元函数和友元类。12.10.1友元函数

友元函数是定义在类外部的普通函数,但需要在类内进行说明,在说明时前面加以关键字friend。友元函数不是成员函数,但是它能够访问类中的私有成员。friend返回类型函数名(参数类型表);类中友元函数的原型说明classmyClass{private:intvalue;public:friendvoidFriendSet(myClass&ob,intv);};voidFriendSet(myClass&ob,intv)//友元函数的定义中不能加friend关键字{ob.value=v;}voidmain(){myClassfri;FriendSet(fri,10);}12.10.1友元函数几点说明:1)友元函数与成员函数的区别:Set()是类的成员函数,编译器调用Set函数时,会把this指针作为隐含参数传递给它。FriendSet是类的友元函数,不属于myClass类的成员函数。编译器调用它时,没有this指针传递给它。因此,在友元函数的参数中都必须明确、“显式”地指明要访问的对象,以表明它究竟访问的是哪个对象的成员。2)如果在类中说明友元函数时,给出了该函数的函数体代码,则该友元函数也是内联的。3)类的成员函数可以用作其他类的友元。4)友元函数可以同时用作多个类的友元。classComplex{private:doublereal,imag;public:Complex(doubler=0,doublei=0);voidprint()const;//复数运算friendComplexoperator+(constComplex&c1,constComplex&c2);friendComplexoperator-(constComplex&c1,constComplex&c2);friendComplexoperator-(constComplex&c);};

intmain(){Complexc1(2.5,3.7),c2(4.2,6.5);Comp

温馨提示

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

评论

0/150

提交评论