C#讲义(面向对象部分).doc_第1页
C#讲义(面向对象部分).doc_第2页
C#讲义(面向对象部分).doc_第3页
C#讲义(面向对象部分).doc_第4页
C#讲义(面向对象部分).doc_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

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

文档简介

第3章 面向对象的程序设计3.1 面向对象程序(OOP)设计概述3.1.1 面向过程与面向对象程序设计 面向过程的程序设计面向过程的程序设计是基于过程的语言(如C)常用的一种编程方法。它主要是强调把整个系统划分为细小的功能模块,称为过程,每个过程用以实现不同的功能,使用的时候按预定的步骤调用就可以了。同时,还要编写一个具有程序入口功能的主程序,当运行一个软件时,主程序会先运行,并按照用户的需要调用其他过程,直到程序运行结束。由此可见,面向过程的程序的执行方式是过程驱动或步骤驱动。当完成一个程序设计后,如果程序的功能变了,就必须修改程序或重新设计程序,因此,面向过程的程序设计方式代码重用率很低,不便于维护。面向过程程序设计模式:例如:开发五子棋游戏软件,面向过程的设计思路就是首先分析问题的步骤:开始游戏绘制画面黑子下棋绘制画面判断输赢白子下棋绘制画面判断输赢返回步骤 输出最后结果把上面每个步骤用分别的函数来实现,问题就解决了。 存在着如下缺陷:(1) 以过程(功能)为单位,不能和现实世界很直观地映射 ,不易于理解。(2) 程序的定律是:程序=(算法)+(数据结构),而传统的程序设计方法是算法和数据分离的。(3) 面向功能的分解,而用户的改变绝大多数是面向功能的改变,功能实现分散在各过程中,不易于维护和功能扩展。(4) 数据结构与算法分离,不利于信息隐藏。如下棋规则变了,必须修改与规则相关的各过程,再比如要加入悔棋功能,那么从输入到判断到显示这一连串的步骤都要改动。 面向对象程序设计面向对象的程序设计OOP(Object Oriented Programming)是在面向过程的基础上发展起来的一种新的程序设计思想。在面向对象的程序设计中,将系统分成若干个功能实体,称为对象,对象是构成程序的基本单位和运行实体。每一个对象都有自己的数据和行为,它们均被封装在对象内部,通过这样若干个对象的相互作用来实现程序设计的设计目标。 同样分析五子棋游戏,只需为该系统创建以下几类对象:(1)黑白双方对象:这两种对象除了颜色不一样外,其余的数据和行为都是一模一样的。(2)棋盘对象:负责绘制画面。(3)规则对象:负责判定诸如犯规、输赢等。当程序运行时,第一类对象(黑白双方对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。 可以看出,这种思想方式,完全与现实世界相吻合。面向对象程序设计模式:面向过程的程序的执行路线是代码事先确定好的,而面向对象的程序的执行则是由事件驱动实现的,也就是说完全取决于用户在使用程序时激活了什么事件,这种程序执行方式叫事件驱动方式。演示学生公寓管理系统,理解事件驱动。3.1.2 面向对象程序设计的基本概念 抽象(Abstract ) 从许多事物中舍弃个别的、非本质的特征,抽取共同的、本质性的特征,就叫做抽象。抽象是形成概念的必须手段。抽象原则有两方面的意义:第一,尽管问题域中的事物是很复杂的,但是分析员并不需要了解和描述它们的一切,只需要分析研究其中与系统目标有关的事物及其本质性特征。第二,通过舍弃个体事物在细节上的差异,抽取其共同特征而得到一批事物的抽象概念。抽象是面向对象方法中使用最为广泛的原则。抽象原则包括过程抽象和数据抽象两个方面。过程抽象是指,任何一个完成确定功能的操作序列,其使用者都可以把它看做一个单一的实体,尽管实际上它可能是由一系列更低级的操作完成的。数据抽象是指根据施加于数据之上的操作来定义数据类型,并限定数据的值只能由这些操作来修改和观察。数据抽象是面向对象分析的核心原则。它强调把数据(属性)和操作(服务)结合为一个不可分的系统单位(即类),类的外部只需要知道它能做什么,而不必知道它如何做。 对象(Object)对象是面向对象程序设计的基础,有时也称为实例,它有自己的成员和特征,对象是运行期的基本实体。如一个按钮,一个标签等都是对象。 类(Class)类是对同类对象的抽象,通过类我们可以创建若干个对象,我们可以认为类是对某类实体的综合描述和定义,而对象是一个确确实实的个体。类是一组具有相同数据结构和相同操作的对象的集合,是对一系列具有相同性质的对象的抽象,是对对象的共同特征的描述。如:图纸(类)如汽车就是一个类,而某辆具体的汽车就是该类的一个实例,称为对象。实体现实世界抽象数据类型概念世界对象类计算机世界抽象逻辑实现物理映射抽象实例化 封装(Encapsulation)封装是面向对象技术的一个重要原则,把数据和函数及其服务包装在一个单独的单元(称为类)的行为称为封装。它尽可能的隐蔽对象的内部细节,而外部只能通过接口与之发生联系。面向对象编程的封装性原则要求不能直接访问类中的数据成员。这主要是因为: 如果直接访问类的数据成员,就必须充分了解类的实现细节,这有悖于隐藏设计细节的思想,会限制代码的重用性和维护性。 如果直接访问类的数据成员,就可能有意或无意地破坏对象中的数据,可能会导致难以调试的程序缺陷。 继承(Inheritance)继承是可以让某个类型的对象获得另一个类型的对象的属性的方法。如:在OOP中,继承的概念很好的支持了代码的重用性。 重载(Overload) 重载是指让同名的方法或运算符具有不同功能,可以根据不同的参数执行不同的功能。重载包含方法重载和运算符重载两大类。如让max函数既可以求数值型数据的最大值,也可以求字符串型数据的最大值;让运算符即可以求实数的和,也可以求复数的和等。 多态性(Polymorphism)多态是OOP的另一个重要概念。多态的意思是事物具有不同形式的能力,即多种形态。方法的重载和抽象类都是多态的表现。如:多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。多态在实现继承的过程中被广泛应用。因此面向对象程序设计的特性有:抽象封装继承多态(有严格的时序性)3.2 类与对象在C中,使用类之前应先定义类,再根据类生成实例-对象,一个C程序至少应包含一个类。3.2.1 类的声明格式:modifiers class identifier :base-listclass-body;说明:1、modifiers:修饰符,C中的修饰符有new、abstract、sealed和四个访问修饰符:public、protected、internal、private、internal等。在C#中类可以嵌套定义,最外层的类称为顶级类。适应于顶级类的修饰符人有:abstract、sealed、public和internal,默认的类修饰符为internal。(1) abstract :抽象类或不完整类,该类只能是其他类的基类。(2) sealed:密封类,不能被继承。将密封类用作基类是错误的。在类声明中使用sealed修饰符可防止继承此类。sealed和abstract不能同时施加在同一个类前。(3) internal 关键字是类和类成员的访问修饰符。只有在同一程序集的文件中,内部类或成员才是可访问的2、identifier:类名3、base-list:即该类继承的基类和多个接口的列表,各项之间由逗号分隔。4、class-body:类成员的声明。3.2.2 对象的声明格式:类名 对象名=new 类名(参数);或分成两步:类名 对象名;对象名=new 类名(参数);例:using System;class studentprivate string no;private string name;private int age;private char sex;private double aver;public student(string sno,string sname,int sage,char ssex,double saver)no=sno;name=sname;age=sage;sex=ssex;aver=saver;public void dispstudent()Console.WriteLine(学号:0姓名:1 年龄:2 性别:3 平均成绩:4,no,name,age,sex,aver);static void Main()student s1,s2;s1=new student(101,张三,20,男,88);s1.dispstudent();s2=new student(102,李四,19,女,90);s2.dispstudent();3.2.3 类的成员 成员分类类的成员可以是本类中直接声明的成员,或者从它的基类中继承来的成员。类中的成员可以有:成员含义常量(Constant)表示一个和类相关的常量值字段(Fields)表示类中的变量方法(Methods)用来实现计算和类的功能属性(properties)定义一个类的属性,通过读和写操作这个属性事件(Events)定义一个类产生的动作索引(Indexers)允许类的实例像访问数组一样被访问操作符(Operators)定义一个可以被类的实例使用的操作符号构造函数(Instance Constructors)初始化类的实例,在创建类实例时被自动执行析构函数(Destructors)在类被destory之前自动调用析构函数,静态构造函数(Static Constructors)在初始化类本身的时候使用类型(Type)代表类内部的类型 类成员的可访问性通过权限修饰符指定声明的类型和类型成员的可访问性。主要有以下几种:(1) 公有(Public):成员对于任何人都是可见的,访问不受限制(2) 私有(Private):成员是隐藏的,只有对类本身是可用的,不能被继承。(3) 受保护(Protected):成员和私有成员类似,只能由包含它的类或其派生类访问,这样既可以方便派生类使用,又可以对外界隐藏。(4) 内部(Internal):成员对整个应用程序是公有的,但对于其他的外部应用程序是私有的。当我们希望其他应用程序能够使用当前应用程序中的包含的一个类,但又希望这个类为当前应用程序保留一定的功能时,就要用到内部。(5) 受保护内部(Protected Internal):成员只能由包含了基类的应用程序中的从该基类派生的子类所访问。类成员的默认修饰符是private。 静态和实例成员对类中的成员,要么是静态成员,要么是实例成员。静态成员:是指用static修饰符声明的成员, 静态成员的访问方式为:类名.成员名。 一个静态字段只指明了一个存储位置,无论有多少个实例被创建,静态字段还是只有一个,而不会产生多个。注意:若在本类中访问静态成员,类名可以省略。实例成员:或称非静态成员,指没用static修饰符声明的成员。 每次类实例化的时候,就创建所有的新的实例字段。例1:此例说明了静态成员和非静态成员的访问方法。using System;class Class1 public int x; /定义非静态字段x public static int y; /定义静态字段y public void f1() /定义非静态方法f1() Console.WriteLine(f1 is a instance method!); public static void f2() /定义静态方法f2() Console.WriteLine(f1 is a static method!); class Class2 static void Main() Class1 objofclass1 = new Class1(); objofclass1.x = 100; Class1.y = 200; Console.WriteLine(x=0,y=1, objofclass1.x, Class1.y); objofclass1.f1(); Class1.f2(); 用string类中的Format方法和Insert方法加以说明。例2:此例说明了静态成员与动态成员的区别。using System;class ClassApublic int x=1;public static int y=1;public ClassA() /定义构造函数x+;y+;class ClassBstatic void Main()ClassA myclass1=new ClassA(); /创建第一个实例Console.WriteLine(myclass1.x);Console.WriteLine(ClassA.y);ClassA myclass2=new ClassA(); /创建第二个实例Console.WriteLine(myclass2.x);Console.WriteLine(ClassA.y);ClassA myclass3=new ClassA(); /创建第三个实例Console.WriteLine(myclass3.x);Console.WriteLine(ClassA.y);3.3 构造函数和析构函数3.3.1 构造函数对象在初始化时,由于具有特定的意义,有时还要分配内存空间,因此,需要有意义的初始值,并完成相应的操作。例如,一张桌子,要有相应的重量、高度、宽度、长度。一个学生,要有姓名、学号,性别、专业等。对象在创建完再进行初始化是不合适的。由于类的数据成员一般都是私有的或受保护的,不允许外部直接访问,因此,不能象其它变量一样进行简单的初始化。解决的办法就是构造函数构造函数的主要功能是创建对象,为对象分配存储空间,并完成对类实例的初始化,对构造函数要注意以下几个问题:(1) 构造函数签名必须与类名一致。(2) 构造函数不能被继承,但可以重载。(3) 如果一个类不包含构造函数,则系统会提供一个默认的构造函数。(4) 构造函数在类的实例被创造时被自动调用,不能显式调用(但在子类的构造函数可以调用基类的构造函数),因而也不用声明返回类型。(5)构造函数的访问修饰符一般是public,如果是private,则表示这个类不能被派生,也不能被实例化,这通常用于只含有静态成员的类中。例:using System;class Pointpublic double x,y;public Point()this.x=0;this.y=0;public Point(double x,double y)this.x=x;this.y=y;class teststatic void Main()Point a=new Point();Point b=new Point(3,4);(6)可以在构造函数前加static关键字形成静态构造函数,但要注意,静态构造函数用于实现初始化类(而不是初始化实例或对象)所需的操作。类的静态构造函数在给定程序中至多执行一次。在程序中第一次发生以下事件时将触发静态构造函数的执行:创建类的实例。引用类的任何静态成员。如果类中包含用Main方法,那么该类的静态构造函数将在调用Main方法之前执行。如果类包含任何在声明时初始化的静态字段,则在执行该类的静态构造函数时,先要按照顺序执行那些初始化。比如:/ 静态构造函数的例子using System;class Test static void Main() A.F(); B.F(); class A static A() / 静态构造函数 Console.WriteLine(执行A的静态构造函数来初始化A); public static void F() Console.WriteLine(调用A.F(); class B static B() / 静态构造函数 Console.WriteLine(执行B的静态构造函数来初始化B); public static void F() Console.WriteLine(调用B.F(); 3.3.2 析构函数析构函数用于销毁类的实例。析构函数是自动调用的,它不能被显式调用。当任何代码都不再可能使用一个实例时,该实例就符合被销毁的条件。此后,它所对应的实例析构函数随时均可能被调用,但是调用时机由公共语言运行时的垃圾回收机制确定,而不是由用户程序确定。其声明形式如下: 类名( ) 函数体注意: C#的析构函数不会在对象无效时被立即执行。所以,如果某种资源需要在对象无效时立即被释放,那么释放这种资源的代码就不应该在析构函数中。3.4 关键字this关键字this有两种基本的用法,一是用来进行this访问,二是在声明构造函数时指定需要先执行的构造函数。3.4.1 this访问在类的实例构造函数和实例函数成员中,关键字this表示当前的类实例或者对象的引用。this不能用在静态构造函数和静态函数成员中,也不能在其他地方使用。当在实例构造函数或方法内使用了与字段名相同的变量名或参数名时,可以使用this来区别字段和变量或者参数。下面的代码演示了this的用法。public class Dog public string name; public int age; public Dog() public Dog(string name) / 在这个函数内,name是指传入的参数name = name; / 表示字段name public Dog(string name, int age) / 在这个函数内,name是指传入的参数name / age是指传入的参数age = name; / 表示字段name this.age = age; / this.age表示字段age 实际上,this被定义为一个常量,因此,虽然在类的实例构造函数和实例函数成员中,this可以用于引用该函数成员调用所涉及的实例,但是不能对this本身赋值或者改变this的值。比如,this+,-this之类的操作都是非法的。3.4.2 this用于构造函数声明可以使用如下的形式来声明实例构造函数:访问修饰符【类名】(形式参数表) : this(实际参数表) 【语句块】其中的this表示该类本身所声明的、形式参数表与实际参数表最匹配的另一个实例构造函数,这个构造函数会在执行正在声明的构造函数之前执行。比如:/ 关键字this用于声明构造函数using System;class A public A(int n) Console.WriteLine(A.A(int n); public A(string s, int n) : this(0) Console.WriteLine(A.A(string s, int n); class Test static void Main() A a = new A(A Class, 1); 此例说明,执行构造函数A(string s, int n)之前先执行了构造函数A(int n)。3.5 域(字段)域又称为字段,指类中或实例中的变量。3.5.1 静态和实例字段略3.5.2 只读字段readonly 关键字是可以在字段上使用的修饰符。当字段声明包括 readonly 修饰符时,该声明引入的字段赋值只能作为声明的一部分发生,或者发生在同一类的构造函数中。对只读字段,只能在下列上下文中进行赋值: (1) 当在声明中初始化变量时,例如: public readonly int y = 5;(2) 对于实例字段,在包含字段声明的类的实例构造函数中;或者,对于静态字段,在包含字段声明的类的静态构造函数中。只有在这些上下文中时,将 readonly 字段传递为 out 或 ref 参数才有效。 / cs_readonly_keyword.cs/ Readonly fieldsusing System;public class ReadOnlyTest class MyClass public int x; public readonly int y = 25; / Initialize a readonly field public readonly int z; public MyClass() z = 24; / Initialize a readonly instance field public MyClass(int p1, int p2, int p3) x = p1; y = p2; z = p3; public static void Main() MyClass p1= new MyClass(11, 21, 32); / OK Console.WriteLine(p1: x=0, y=1, z=2 , p1.x, p1.y, p1.z); MyClass p2 = new MyClass(); p2.x = 55; / OK p2.y=100; /error Console.WriteLine(p2: x=0, y=1, z=2 , p2.x, p2.y, p2.z); 注意:如果一个值在整个程序中保持不变,并且在编写程序时就已经知道这个值,那么就应该使用常量。如果这个值在编写程序时不知道,而是程序运行时才能得到,而且一旦得到这个值,值就不会在改变,那么就应该使用只读变量。3.6 方法方法(method)用来计算和实现类的功能,通常在C#中,把函数称为方法。3.6.1 定义定义函数的一般格式为:修饰 返回值类型 函数名(参数) 代码块Return 返回值 例:定义一函数求两数的较大值。注意:当没有返回值时,要使用关键字void。3.6.2 调用1、在函数调用时,参数与定义时的参数必须匹配。2、若要通过引用传递参数,在定义和调用时加关键字ref即可。3.6.3 输出参数在调用一个方法时,要进行相应的参数传递。参数有以下几类:(1) 值参数(value parameters):即为常量值,即为值传递,不需要修饰符。(2) 引用参数(reference parameters):即为地址传递,用ref修饰。(3) 输出参数(output parameters):用out修饰符。(4) 参数数组(params parameters):用params修饰符。有时若希望从函数中返回多个值,就要使用输出参数-out关键字。此时只需在定义和调用时使用此关键字即可,但要注意,在调用的模块中对该变量无需进行初始化,若已经初始化,则在调用时其原值会丢失。using System;class myclass public static int max(int a, int b,out int c) int max; if(ab) max=a; else max=b; c=a+b; return max; static void Main() int x=10; int y=20; int z; /定义即可,无需初始化。 Console.WriteLine(max(x,y,out z); Console.WriteLine(a=0,b=1,z=2,x,y,z); using System;class Testpublic int a; public static int b;public Test(int m,int n)a=m;b=n;public void DMeth() a=a+5;b=b+5;public static void SMeth()/ a=a+5;b=b+5;class Exampublic static void Main()Test t1=new Test(5,10);Test t2=new Test(15,20);t1.DMeth();t2.DMeth();/t1.SMeth();/t2.SMeth();Test.SMeth();/Console.WriteLine(t1.a=0,t1.b=1,t1.a,t1.b);Console.WriteLine(t1.a=0,Test.b=1,t1.a,Test.b);/Console.WriteLine(t2.a=0,t2.b=1,t2.a,t2.b);Console.WriteLine(t2.a=0,Test.b=1,t2.a,Test.b);分析程序中绿色部分的原因及程序的执行结果。3.6.4 参数数组params 关键字可以指定在参数数目可变处采用参数的方法参数,即当实参的数目不固定时,可用该关键字修饰形参,以定义一个参数数组。例:using System;class ParamsTest static void ParamsMeth(ref int sum,params int arr )int i;for(i=0;iarr.Length;i+)sum=sum+arri;arri=arri*arri;static void Main()int a=1,2,3;int i,s=0;ParamsMeth(ref s,a);Console.WriteLine(和为0,s);for(i=0;ia.Length;i+)Console.WriteLine(a0=1,i,ai);ParamsMeth(ref s,23,45);Console.WriteLine(和为:0,s);ParamsMeth(ref s,1,2,3,4,5,6,7,8,9,10);Console.WriteLine(和为:0,s);练习:分析下面程序的执行结果/ cs_params.csusing System;public class MyClass public static void UseParams(params int list) for ( int i = 0 ; i list.Length ; i+ ) Console.Write(0 ,listi); Console.WriteLine(); public static void UseParams2(params object list) for ( int i = 0 ; i y) return x;elsereturn y;public string max(string x,string y)if (string.Compare(x,y)0) return x;elsereturn y;static void Main()Console.WriteLine(new myclass().max(10,20);Console.WriteLine(new myclass().max(dabc,abc);3.6.6 运算符重载运算符重载主要是给运算符赋予不同的功能,例如,“”可以求数值型数据的和,也可以对字符串型数据进行连接等。可以重载的操作符有:一元:+ - ! + - true false二元:+ - * / % & | = != = 0 )Console.WriteLine(0+1i,a,b);elseConsole.WriteLine(0-1i,a,-b); class Testpublic static void Main()int sn;string sc;Complex x=new Complex(1,2); x.DispCom();Complex y=new Complex(3,4); y.DispCom();Complex z=new Complex(0,0); z=x+y;z.DispCom();sn=10+20;sc=abc+123;Console.WriteLine(0,1,sn,sc);3.6.7 外部方法外部方法主是是为C#提供了一种访问其它语言(如C+)中定义的函数及Windows API函数的方法。基本过程: (1)引入System.Runtime.InteropServices命名空间。(2)引入动态链接库及函数的入口: DllImport(KERNEL32.DLL, EntryPoint=MoveFileW, SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall) 其中入口点EntryPoint标识函数在动态链接库的入口位置。(3)函数声明所有外部方法都要声明为static,并冠以extern,表明该方法为外部方法,但不要实现。public static extern bool MoveFile(String src, String dst); 注意:可以把这个入口点映射为一个不同的名字,也就是对函数进行重命名。若要实现此功能,则(1)中EntryPoint可省略。(4)函数调用跟其他函数的调用一样。using System;using System.Runtime.InteropServices;namespace ConsoleApplication10 class Program DllImport(KERNEL32.DLL, EntryPoint = MoveFileW, SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall) public static extern bool MoveFile(String src, String dst); DllImport(user32.dll, EntryPoint = MessageBox) public static extern int MsgBox(int hWnd, String text, String caption, uint type); static void Main(string args) if (MoveFile(e:2.txt, c:1.txt) = true) MsgBox(0, 文件移动成功!, 系统提示, 1); else MsgBox(0, 对不起!,原文件不存在, 系统提示, 1); 3.7 属性属性(Properties)是字段的自然扩充,访问属性和访问字段的句法是一样的,但与字段不一样的是,属性具有良好的封装性,属性可通过访问器来读写或计算它们的值。对属性的简单声明格式如下: modifiers type attributename accessor-declaration3.7.1 访问器属性的访问器包含与获取(读取或计算)或设置(写)属性有关的可执行语句。访问器声明可以包含 get 访问器或 set 访问器,或者两者均包含。声明的格式如下:set accessor-bodyget accessor-body对一个属性,可以仅有set访问器或get访问器,也可以都有。 set访问器set 访问器主要是用来给属性赋值,其定义与返回 void 的方法类似。它使用称为 value 的隐式参数,此参数的类型是属性的类型。在下例中,set 访问器被添加到 Name 属性:private string name;public string Name set name = value; 当对属性赋值时,用提供新值的参数调用 set 访问器。例如:e1.Name = Joe; / The set accessor is invoked here get访问器get 访问器主要用于访问该属性,基定义与方法体相似。它必须返回属性类型的值。执行 get 访问器相当于读取字段的值。如:private string name; / the name fieldpublic string Name / the Name property get return name; 下面看一个具体的例子:using System;class Person private string myName = N/A; private int myAge = 0; / 声明一个字符型的属性Nam

温馨提示

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

评论

0/150

提交评论