定义c类ppt课件.ppt

上传人:本田雅阁 文档编号:2573937 上传时间:2019-04-11 格式:PPT 页数:61 大小:352.51KB
返回 下载 相关 举报
定义c类ppt课件.ppt_第1页
第1页 / 共61页
定义c类ppt课件.ppt_第2页
第2页 / 共61页
定义c类ppt课件.ppt_第3页
第3页 / 共61页
亲,该文档总共61页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《定义c类ppt课件.ppt》由会员分享,可在线阅读,更多相关《定义c类ppt课件.ppt(61页珍藏版)》请在三一文库上搜索。

1、第11章 定义C+类,类是面向对象程序设计的核心,它实际上是一种新的数据类型,也是实现抽象类型的工具,因为类是通过抽象数据类型的方法来实现的一种数据类型。 类的定义 类:类是一种复杂的数据类型,它是将不同类型的数据与和这些数据相关的操作封装在一起的集合体,因此,类具有更高的抽象性,类中的数据具有隐藏性,类还具有封装性。 类包括:描述属性的数据和处理数据的方法(行为)。 对象是类的实例。对象将其属性和行为封装在一起,并将其内部大部分的实现细节隐藏起来,仅通过一个可控的接口与外界交互。,面向对象程序设计的特点,一、抽象性,抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程。

2、 先注意问题的本质及描述,其次是实现过程或细节。 数据抽象:描述某类对象的属性或状态(对象相互区别的物理量)。 代码抽象:描述某类对象的共有的行为特征或具有的功能。 抽象的实现:通过类的声明。,抽象实例钟表,数据抽象: int Hour, int Minute, int Second 代码抽象: SetTime(), ShowTime(),抽象实例钟表类,class Clock public: void SetTime(int NewH, int NewM, int NewS); void ShowTime(); private: int Hour,Minute,Second; ;,二、封装,

3、将抽象出的数据成员、代码成员相结合,将它们视为一个整体。 目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员。 实现封装:在c+中,利用类的形式实现封装的。,实例: class Clock public: void SetTime(int NewH,int NewM, int NewS); void ShowTime(); private: int Hour,Minute,Second; ;,边界,特定的访问权限,类实现了对数据的有效隐蔽和合理控制,是问题的属性和行为的有机和谐的统一。,三、继承与派生,是C+中支持层次分类的一种机制

4、,允许程序员在保持原有类特性的基础上,进行更具体的说明。 新的类由原有的类产生,我们说新类继承了原有类的特征,或者说原有类派生出新类。 实现:声明派生类第12章,四、多态性,多态:是指类中具有相似功能的不同函数使用同一个名称来实现的现象。只是人类思维方式的一种直接模拟,比如说“打球”的这个“打”,就是一个多态现象。打篮球、打羽毛球等规则和实际“打”的操作相差甚远,只是功能相似,我们就统一使用“打”来表示。 目的:达到行为标识统一,减少程序中标识符的个数。 实现:重载函数和虚函数第14章,11.1 类的定义,类是一种用户自定义类型,声明形式: class 类名称 public: 公有成员和函数(

5、外部接口) private: 私有成员和函数 protected: 保护型成员和函数 ,在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。,在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。 如果紧跟在类名称的后面声明私有成员,则关键字private可以省略。,与private类似,其差别表现在继承与派生时对派生类的影响不同,第12章讲。,class Clock public: void SetTime(int NewH, int NewM, int NewS); void ShowTime(); private:

6、 int Hour, Minute, Second; ;,成员数据:与一般的变量声明相同,但需要将它放在类的声明体中。,成员函数:在类中说明原形,可以在类外给出函数体实现,并在函数名前使用类名加以限定。也可以直接在类中给出函数体,形成内联成员函数。 允许声明重载函数和带默认形参值的函数,void Clock : SetTime(int H, int M,int S) Hour=H; Minute=M; Second=S; void Clock : ShowTime() coutHour“:“Minute“:“Second; ,11.2 对象的生成,类的对象是该类的某一特定实体,即类类型的变量。

7、 声明形式: 类名 对象名; 例: Clock myClock;,类中成员的访问方式,类中成员互访 直接使用成员名 类外访问 使用“对象名.成员名”方式访问 public 属性的成员,例11.1类的应用举例,#include class Clock /时钟类的声明 public: /外部接口,公有成员函数 void SetTime(int NewH, int NewM, int NewS); void ShowTime(); private: /私有数据成员 int Hour,Minute,Second; ; /时钟类成员函数的具体实现 void Clock:SetTime(int H, in

8、t M, int S) Hour=H; Minute=M; Second=S; void Clock:ShowTime() coutHour“:“Minute“:“Secondendl; ,void main() Clock myClock; myClock.Hour=20;/? myClock.Minute=40;/? myClock.Second=26;/? coutmyClock.Hour“:“myClock.Minute“:“myClock.Secondendl; ,void main() Clock myClock; myClock.SetTime(20,40,26); myCloc

9、k.ShowTime(); ,优点:,1、允许类设计人员检查赋予数据成员的任何数值的有效性。程序其它部份无法给它们赋值,只有通过初始化函数或构造函数。 2、在类中可以随意改变这些数据结构的设计而不影响其它程序。,11.3对象的初始化,在类中有两个特殊类型的成员函数: 构造函数 constructor 析构函数 destructor,一、构造函数,构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态。 在对象创建时由系统自动调用。 如果程序中未声明,则系统自动产生出一个默认形式的构造函数 允许为内联函数、重载函数、带默认形参值的函数,1. 构造函数举例,clas

10、s Clock public: Clock (int NewH, int NewM, int NewS);/构造函数 void SetTime(int NewH, int NewM, int NewS);/初始化成员函数 void ShowTime(); private: int Hour,Minute,Second; ;,构造函数的实现: Clock:Clock(int NewH, int NewM, int NewS) Hour= NewH; Minute= NewM; Second= NewS; 建立对象时构造函数的作用: void main() Clock c (0,0,0); /隐含

11、调用构造函数,将初始值作为实参。 c.ShowTime(); ,注:、构造函数与类同名,定义构造函数时, 不能指定返回值。 、构造函数在生成类对象时自动调用。 、new操作符自动调用生成对象的构造函数。 Clock *myclock=new Clock(10,25,10) ; 这是new比malloc函数的一个重要优势。,2、缺省构造函数 缺省构造函数:没有参数的构造函数。 缺省构造函数初始化数据成员时常赋予缺省值。,class Clock public: Clock( ) Hour=Minute=Second=0;/缺省构造函数 Clock (int NewH, int NewM, int

12、NewS);/构造函数 void SetTime(int NewH, int NewM, int NewS); void ShowTime(); private: int Hour,Minute,Second; ;,注: 如果没有定义特定类的构造函数,则编译器会自动生成缺省构造函数。 如果类有缺省构造函数(用户定义或编译器生成),则可以不传递参数而定义类对象。 例: Clock myclock ;,如果不向构造函数传递参数,不要在对象定义中加上空括号,否则系统会声明一个返回类类型的函数而不是定义类实例。 Clock myclock ( ) ; /声明函数myclock. Clock myclo

13、ck ( 10,12,50 ),如果定义了类的构造函数,则编译器不再生成缺省构造函数。因此,如果定义了一个或几个构造函数,但其中不包括缺省构造函数,则类不会有缺省构造函数。 注意:使用没有缺省构造函数的类有时会产生错误。(数组初始化),不允许在类定义中初始化数据成员。 下列类定义是错误的 class c private : int Hour=10,Minute=20,Second=30; ,3、成员初始化表 成员初始化表应放在构造函数定义中参数表的紧后方,包括冒号和一个或几个用逗号隔开的项。 每一项包括数据成员名和括号内的初始化值。例如: class Clock public: Clock (

14、)Hour=Minute=Second=0; Clock (int NewH, int NewM, int NewS):Hour(NewH),Minute(NewM),Second(NewS); void ShowTime(); private: int Hour,Minute,Second; ; 生成对象 Clock cobject (10,20,30) 则对象cobject中,成员Hour,Minute,Second分别初始化为10,20,30。,4、重载构造函数,class clock private : int hours,minutes,seconds ; public : Cloc

15、k() Hour=Minute=Second=0 ; Clock (int NewH, int NewM, int NewS) Hour= NewH; Minute= NewM; Second= NewS; ; void main() clock myclock1; clock myclock2 ( 25, 25, 25);,和重载全局函数一样,也可以重载类构造函数和类中除析构函数以外的任何其它成员函数。例,5、对象成员(子对象),可以定义一个类作为另一个类的数据成员,即可以将一个类的对象嵌入另一个类的对象中。这种数据成员称为对象成员。 有子对象的构造函数: 构造函数名(参数表):子对象名(参

16、数表),class ccont private : cembeded emb ; /对象成员 public : ccont (int P1,int P2, int P3) :emb ( P1, P2) /对象成员初始化 coutp3endl; void main() ccont c(1,2,3);,class cembeded public : cembeded ( int p1, int p2 )coutp1“,”p2endl; ;,6、成员函数的定义,类中的成员函数,可在类中定义,也可在类中说明,在类外定义。 在类外定义成员函数: 函数值类型 类名:函数名(参数) 可以减少类体的长度,使类

17、体清晰,便于阅读,而且有助于把类的接口和类的实现细节分离。例11.6 p109,7.内联成员函数,总结: 1、在类定义外定义成员函数时,必须在函数名前加上类名和作用域操作符:。 2、类内外定义的函数之间有个重要的区别:类内定义的函数被当作内联函数,而类外定义的函数缺省当作非内联函数。 短函数可以定义在类?,长函数定义在?。 3、如果也想把类外定义的函数也当作内联函数,可用inline关键字。,成员函数定义在类内和类外有个重要区别:类内定义的函数被当做内联函数,而类外定义的函数缺省当做非内联函数。若要把类外定义的函数当做内联函数,可以用inline关键字。 inline 函数值类型 类名:函数名

18、(参数) ,#include “iostream.h“ int a=0,b=0; class A public: int a,b; void f(int c=2,int d=3) a=c;b=d; ; void f(int c=3,int d=4) a=c; b=d; void main() A n; n.f(); coutn.a n.bendl; f(); coutn.a n.bendl; n.f(7,8); couta bendl; ,8.对象与指针,可以定义指向对象的指针,方法与声明指向基本数据类型变量的指针相同。 Clock myclock ; Clock *ptr= 释放,void

19、set(char *string) delete Buffer; Buffer=new charstrlen(string)+1; strcpy(Buffer,string); ; void main() CMessage m; m.set(“hello“); m.display(); ,1、析构函数:用来释放对象,在对象删除前,用它来做一些清理工作,它在类对象销毁时自动调用。,二.析构函数,#include“iostream.h“ #include“string.h“ class CMessage private : char *Buffer ; public : CMessage() Bu

20、ffer=new char (0); CMessage() delete Buffer ; void display() coutBuffer; ,注: (1)析构函数与类同名,前面加上号。 (2)和构造函数一样,析构函数不能定义返回类型。 (3) 与构造函数不同的是,析构函数不能接收参数。 (4) 如果类中没有定义析构函数,编译系统会自动生成缺省析构函数(空函数)。 (5) 析构函数不能重载。 (6) 一个类中只能定义一个析构函数。,2、何时调用构造函数和析构函数。 构造函数在对象生成时调用 析构函数在对象销毁时调用 特定类型对象构造函数和析构函数的调用:, 对全局定义的对象: 构造函数在程

21、序开始运行时调用,即在main接到控制前调用。析构函数在程序结束时调用。, 对于局部定义的对象: 构造函数在控制流到达对象定义时调用,析构函数在控制传出定义对象的块时(即包含对象的函数退出时)调用。,(3) 对于用static关键字局部定义的对象: 构造函数在控制首次到达对象定义时调用,析构函数在程序结束时调用。,(4) 对于用new操作符动态生成的对象: 构造函数在对象生成时调用,析构函数在对象用delete操作符明确销毁时调用(如果不明确销毁对象,则析构函数永远也不调用)。,#include“iostream.h”/example11.8 #include“string.h“ void f

22、un(); class AA public: AA(char *str) string=new charstrlen(str)+1; strcpy(string,str); cout “Constr “stringendl; AA() cout“Destru“stringendl; delete string; private: char *string; ;,AA b(“global object“); void main() AA *a; a=new AA(“new object“); fun(); delete a; void fun() cout“come in fun“endl; A

23、A aa(“function object“); static AA bb(“static object“); cout“go out fun“endl; ,运行结果: Constr global object Constr new object come in fun Constr function object Constr static object go out fun Destru function object Destru new object Destru static object Destru global object,调用构造函数和析构函数的顺序,对于相同的对象:先构造

24、的后析构,后构造的先析构,相当于一个栈,先进后出。 分析下面程序的运行结果:,例:class student public: student(int n,string nam,char s) num=n; name=nam; sex=s; cout“Constructor called”endl; student() cout“Destructor called”numendl; void display() cout“num:”numendl; cout“name:”nameendl; cout“sex:”sexendl;,private: int num; char name10; cha

25、r sex; ; void main() student stu1(10010,”wang_li”,f); stu1.display(); student stu2(10011,”zhang_fun”,m); stu2.display();,程序运行结果如下: Constructor called num:10010 name:wamg_li sex:f Constructor called num:10011 name:zhamg_fun sex:m Destructor called 10011 Destructor called 10010,判断以下程序的执行结果_. #include

26、class A public: A(int sma) cout“A“ “smaendl; A() cout“Des.“endl; ; void fn(int n) static A sm(n); cout“fn“ “nendl; void main( ) fn(10); fn(20); ,(A) A 10 fn 10 fn 20 Des. (B) A 10 fn 10 Des. A 20 fn 20 Des.,(C) A 10 A 20 fn 10 fn 20 Des. Des. (D) A 10 fn 10 fn 20 Des. Des.,A,判断以下程序的执行结果 #include cla

27、ss A public: A() s=0; A(char *p) s=p; couts“n“; A() couts“n“; private: char *s; ; A a1(“hello“); A ,(C) hello Beijing China China Beijing hello,(A) hello Beijing China China Beijing Beijing China China Beijing hello,(B) hello Beijing China China China China Beijing hello,(D) hello Beijing China Chin

28、a China China hello Beijing,B,1.4 静态(static)类成员,一、静态数据成员 1、定义: class CTest public ; static int count ; ; 注:无论生成多少个CTest对象,只有一个count,因此它是由所有CTest对象共有的。静态数据成员只存储一处,供所有对象共用。,2、初始化 类型名 类名: 静态成员=初值; 在类定义外且函数外初始化。 int CTest : count = 0 ; 3、访问:直接用类名和作用域操作符 void main ( ) CTest : count = 1 ; 4.在类中声明,可以控制对它的访

29、问 ( public , private ),void Add: GetNumber() cout“Number=“Aendl; void Add: GetSum() cout“Sum=“Sumendl; void main() Add M(3); M.GetNumber(); M.GetSum(); Add N(8); N.GetNumber(); M.GetSum(); N.GetSum(); ,#include “iostream.h“ class Add public: Add(int a); void GetNumber( ); void GetSum( ); int A; stat

30、ic int Sum; ; int Add:Sum=0; Add:Add(int a) A=a; Sum+=A; ,二、静态成员函数,1、定义: class CTest static int getcount ( ) ; 2、调用: void main ( ) int Count = CTest : getcount ( ) ; ,注: 调用时用类名和作用域操作符,而不用类对象引用(类对象甚至可以不存在)。 静态成员函数只能直接引用静态数据成员和属于其类的静态成员函数。 静态数据成员和成员函数可用于维护类中的所有对象共享的数据项。,# include “iostream.h“ class Ct

31、est private : static int count ; public : Ctest() +count; Ctest() -count; static int Getcount() return count; ;,int Ctest:count=0 ; void main() coutCtest:Getcount(); cout“object existn“; Ctest Test1; Ctest *Ptest2= new Ctest ; coutCtest:Getcount(); cout“ object existn “; delete Ptest2; coutCtest:Get

32、count() cout“object existn“ ; ,void M:f(M m) cout“A=“m.Aendl; cout“B=“Bendl; int M:B=0; void main() M P(5); M:f(P); M Q(10); M:f(P); M:f(Q); ,(4) 如果静态成员函数中要引用非静态成员,可通过对象来引用。,#include “iostream.h“ class M public: M(int a) A=a;B+=10; static void f(M m); private: int A; static int B; ;,(1) const对象和cons

33、t成员函数 类对象定义中加入const表示不能改变该类中任何数据成员的值。类中的函数定义中加入const表示该函数不能改变任何数据成员的值。 类名 const 对象名(实参表) 或 const 类名 对象名(实参表) const对象不能调用该对象的非const型的成员函数,11.5 const对象和const成员函数,#include class Clock /时钟类的声明 public: /外部接口,公有成员函数 Clock(int NewH, int NewM, int NewS); void ShowTime()const; private: /私有数据成员 int Hour,Minut

34、e,Second; ; /时钟类成员函数的具体实现 Clock:Clock(int NewH, int NewM, int NewS) Hour=NewH; Minute=NewM; Second=NewS; void Clock:ShowTime()const coutHour“:“Minute“:“Secondendl; ,void main() const Clock myClock(20,40,26); myClock.ShowTime(); ,注:常对象必须将其中的函数定义成常成员函数(构造函数除外),才能通过常对象调用常成员函数。(上例中,若ShowTime()不是常函数,则不能调

35、用myClock.ShowTime();即使该函数并没有改变常参数,但编译器不允许。,例:11.13 #include class R public: R(int rl ,int r2)Rl=rl;R2=r2; void print(); void print( )const; private: int R1,R2; ; void R:print ( ) coutR1“:“R2endl; void R:print( )const /常成员函数,重载 coutR1“;“R2endl; void main() R a(5,4); a.print( ); const R b(20,52); b.pr

36、int( ); ,A:A(int i):a(i),r(a) void A:print( ) couta“:”“:”rendl; void main() A al(100),a2(0); al.print(); a2.print(); ,成员初始化表,(2) 常数据成员 常数据成员只能通过构造函数中的成员初始化表的方式来对数据成员初始化。初始化后不能改。,例11.14 #include class A public: A(int i); void print(); const int ,this指针是隐含在成员函数体中的指针,它指向调用该成员函数的对象。,11.6 this指针 #include

37、 “iostream.h“ class CTest public : int N ; CTest(int n)N=n; int GetN() coutN return N; ; void main () CTest Test1(8) ; CTest *Ptest2 = new CTest(5) ; Test1. GetN() ; Ptest2-GetN(); ,例11.16,void time:copy(time ,#include “iostream.h“ class time public: time()h=m=s=0; time(int i,int j,int k) h=i;m=j;s=

38、k; void copy(time ,注;由于静态成员函数可以不引用类对象而调用,所以没有包含对象地址的this指针。因此,如果要直接访问非静态数据成员,则编译器无法确定该数据成员属于哪个类(可通过向函数中传递对象来引用)。 例11.11就是传递对象参数访问非静态数据成员。,11.7 友元 friend,友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但它可以访问类中的私有成员,友元可以是函数,也可以是类。 注:提高了程序的运行效率, 但破坏了封装性。,一、友元函数,#include“iostrea

39、m.h“ #include“math.h“ class squar public: squar(double xx,double yy) x=xx;y=yy; void Getxy(); private: double x,y; ; void squar:Getxy() cout“length:“x“,wide:“yendl; double area(squar /声明为友元才可引用private成员,void main() squar p(3.0,4.0); p.Getxy(); double d=area(p); cout“The areais“dendl; ,friend double

40、area(squar ,二、友元类 在类中声明另一个类为该类的友元类,声明前加friend 。在友元类中可以引用该类中的private成员。,#include“iostream.h“ class X friend class Y; public: void Set(int i)x=i; void Display() coutx“,“yendl; private: int x;static int y; ; class Y public: Y(int i,int j) a.x=i;X:y=j; void Display(); private: X a; int X:y=1;,void Y:Dis

41、play() cout“x=“a.x“,“; cout“y=“X:yendl; void main() X b; b.Set(2); b.Display(); /输出2,1 Y c(6,9); c.Display(); /输出x=6,y=9 b.Display(); /输出x=2,y=9 ,11.8 类的作用域:局部类 、嵌套类,一、类的作用域 类域:它是指在类的定义中由一对花括号所括起来的部份。 注:类域中定义的变量不能使用auto, register, extern修饰符。只能用static修饰符,定义的函数也不能用extern.,二、局部类和嵌套类 1、局部类: 在函数体内定义的类为局部

42、类。 Void fun ( ) class A 注: 局部类中不能说明静态成 员函数,并且所有成员函数 都必须定义在函数体内,很少用。,2、嵌套类 class A public : class B private : ,三.对象的生存期,1、局部对象: 该对象所在函数块进入时,该对象被创建。 该对象所在函数块退出时,该对象被释放。 2、静态对象: 程序第一次执行到所定义的对象时,该对象被创建。 程序结束退出时,该对象被释放。 3、全局对象; 程序开始时,创建该对象。 程序结束时,释放该对象。,11.9 对象指针和对象引用,一、成员的指针,对象的指针,对象的引用 成员的指针 指向数据成员的指针

43、指向成员函数的指针 定义一个指向类A中数据成员C的指针方法如下: 数据类型名 类名:*指针变量名 =,# include “iostream.h“ 例11_19 class A public: A(int i) a=i; int fun(int b) return a*c+b ; int c; private: int a; ; void main ( ) A x(8) ; int A:*PC ; /定义一个指向数据成员的指针 PC= /用对象指针引用成员函数指针调用函数,实参5 /x.fun (*P).fun P-fun P-*pfun ,注: 引用数据成员可以有下面几种形式:(P为指向对象

44、x的指针, P C为指向对象成员C的指针) P-*P C ; P -C; x.*P C ; x.C; 对成员函数的调用可以有下面几种形式(pfun为指向成员函数 fun的指针) ( P -*pfun )(5); P -fun (5); ( x.*pfun ) (5) ; x.fun (5); A &m = x m是对象x的引用。,二、对象指针、 对象引用做函数参数 对象做函数参数,形参改变不影响实参 对象指针、对象引用做函数参数,形参变化,实参也变化,#include “iostream.h“ class M public: M()x=y=0; M(int i,int j)x=i;y=j; v

45、oid copy(M *m); void addxy(int i,int j)x+=i;y+=j; void print()coutx“,“yendl; private: int x,y; ; void M:copy(M *m) *this=*m;,void fun(M m1,M *m2,M ,class DATE public : DATE ( int m, int d, int y ) ; private : ; DATE date 2= DATE (7,22,1998 ),DATE( 7,23,1998 ) ; 或: DATE date 2 ; date0= DATE ( 7,22,19

46、98 ); date1= DATE ( 7,23,1998 ); 初始化的方法有两种:定义的同时初始化; 定义好之后,再单个元素初始化;,11.10 对象数组 一、对象数组定义: 声明: 类名 数组名元素个数; 访问方法: 通过下标访问 数组名下标.成员名,二、对象数组初始化,数组生成时,编译器调用数组中每个元素的构造函数或缺省构造函数,数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象。 通过初始化列表赋值。 例: DATE date 2= DATE (7,22,1998 ),DATE( 7,23,1998 ) ; 如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化(

47、调用默认构造函数)。 不声明构造函数,则采用默认构造函数。 各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数。 各元素对象的初值要求为不同的值时,需要声明带形参的构造函数。 当数组中每一个元素对象被删除时,系统都要调用一次析构函数。 数组元素赋初值时, date0= DATE ( 7,22,1998 ); 会有一个临时的对象产生,调用构造函数,初始化临时对象,之后将临时对象的值赋给date0,然后调用析构函数,释放掉临时对象。,(3) 用new生成的数组不能直接初始化(动态数组),需要每个元素单独初始化。 DATE *date = new DATE 2 ; date0= DATE ( 7,22,1998 ); date1= DATE ( 7,23,1998 ); 销毁时要加上。 Delete date ; 如果省略了,则编译器只对第一个数组元素调用析构函数。,#include using namespace std; class Point pub

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1