C语言基础类的设计.pptx

上传人:莉*** 文档编号:87577538 上传时间:2023-04-16 格式:PPTX 页数:44 大小:202.81KB
返回 下载 相关 举报
C语言基础类的设计.pptx_第1页
第1页 / 共44页
C语言基础类的设计.pptx_第2页
第2页 / 共44页
点击查看更多>>
资源描述

《C语言基础类的设计.pptx》由会员分享,可在线阅读,更多相关《C语言基础类的设计.pptx(44页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、 类是 对象的抽象(泛化),对象 是类的实例(特化)对类也可继续抽象泛化,到极致就得到抽象类(逆过来,抽象类的特化仍是类而非对象)u类设计要点从对象中抽象出类划定属性集和行为集即,确定数据成员和方法成员【要点】只选择与应用域相关的属性及行为,而非无所不包决定外观和私隐即,确定公开接口和细节隐藏 【要点】考虑哪些成员外界可见,哪些对外界隐藏请谨记:以上两点就是面向对象方法的“封装性”的内涵u封装过程 融合于对对象进行抽象分析的过程中本单元着重介绍C#语言机制是如何支持面向对象方法的封装性特征的面向对象技术有四个特征:抽象、封装、继承、多态第2页/共44页第1页/共44页u采用面向对象思维方法来设

2、计程序面向过程与面向对象的比较上一单元WordCount程序实现的功能是:接受命令行参数输入-打开参数所指的文本文件-读取当中文本行并存储起来-分解出文本串中各单词并作次数累计-最后按字典序把各单词出现次数输出到另一个文本文件中。整个设计思路是以过程式方式来进行,特点是,从解决问题的算法过程以及使用的数据结构出发进行设计:程序=算法+数据结构与熟知的C+过程式程序比较,改变的只是代码语法:变量和函数都要写进一个类定义中,思维方式并无本质变化:只是以类的语法来作过程式编程标志是只使用静态函数。2.1 设计第一个类 WordCount class第3页/共44页第2页/共44页 应用面向对象方法设

3、计程序,需要思维上的转变:考虑 建立哪些对象、对象间如何协调以解决问题 程序=对象(=算法+数据)+消息 面向对象的设计思路,首要考虑的是:系统的功能需要哪些对象来完成,即“谁来做”,设计这些对象的所属类时,考虑该类对象所需具备的功能是什么 即通过什么行为来做;“如何做”的考虑被放在次要的位置“推迟实现”的观点:软件开发越迟“实现”,项目越高成功率整个设计过程要把握住:立足全局,由粗到细,由浅入深,由表及里第4页/共44页第3页/共44页u WordCount 类 的设计应从何处着手?开始时,避免过多处理细节考虑,而专注于分析WordCount类的对象(可简称为“单词统计器”)应具有哪些能力,

4、将之罗列出来(如,可分为“打开文件”、“读取文件”、“统计”、”排序并输出结果”等),这些功能就是“单词统计器”应具备的行为特征(成员函数)分析的结果因人而异,有时划分出的某个功能会过于复杂(将太多的工作用一个成员函数来完成)这并非好设计(从开发效率及维护成本找原因)内聚性原则为WordCount 类设立以下成员函数:openFile()readFile()countWords()writeWords()另外为保障上述工作,还需要一些预置作业(初始化任务),而所有工作完成后或许需要进行清理作业(关闭文件,释放资源占用等)第5页/共44页第4页/共44页u成员函数的接口设计确定传入参数和(或)返

5、回值通常,成员函数可 不带参数和返回值,借助类的数据成员完成函数的任务,这样的编程模式较简单可在考虑对象的数据成员同时 调整优化成员函数接口的设计u确定类具有的成员函数(即提取行为特征)后,紧接着应是考虑成员函数的访问级别,这个工作关系到类的信息隐藏效果,这是封装性的要求(回想一下封装的概念)。以下是一些设计原则:可选择的访问级别是public或private,使用public的成员越多,则类细节暴露越多,对类的使用就越不稳定(开发维护难度加大),类成员默认(即不声明时)的访问级别是 private应尽量降低外界对成员函数的直接调用能力。也就是说,在能够实现类承诺功能的前提下,应尽量把成员函数

6、设置为private级别。WordCount对外承诺的功能其实是“统计并输出结果”,目前确定的各个成员函数逻辑上都属于内部运作的子过程,不必也不应该向外公开,应设为private,而另外设立一个public函数processFile()把它们打包,由外界调用。(想想这样做的好处)第6页/共44页第5页/共44页u围绕“谁来做”,类WordCount大体轮廓已能描绘出来(忽略函数的实现细节,象征性以简单屏幕输出来代表函数功能):using System;public class WordCount /单词统计器“产品”的设计蓝图(粗图)public void processFile()openF

7、iles();readFile();countWords();writeWords();private void countWords()Console.WriteLine(“countWords 函数”);private void readFiles()Console.WriteLine(“readFiles(”);private void openFiles()Console.WriteLine(“openFiles函数”);private void writeWords()Console.WriteLine(“writeWords 函数”);第7页/共44页第6页/共44页u 尽管上面的

8、函数没有实现细节,但这个类已经是一个完整的定义,能够成功编译。当然,必须放置Main()函数,并在其中操纵类的实例,这个WordCount类的代码才会真正运作起来。u有两种放置Main()函数的方式第一种是直接在WordCount类定义中 放置Main()函数public class WordCount /产品(部件)设计+装配 图public void processFile().private void countWords()./.public static void Main(string args)/产品装配(设置),自执行/.WordCount wcobj=new WordCoun

9、t();/装配WordCount 对象wcobj.processFile();/操作WordCount实例/./以上构成了WordCount程序的代码(设计蓝图),当编译并运行之,就产生WordCount程序对象实例第8页/共44页第7页/共44页 第二种是另外设计一类作为整个程序的入口,放置Main()函数public class WordCount./产品(部件)设计图public class WordCountEntry/产品装配图(设置)可执行public void static Main(string args)/.WordCount wcobj=new WordCount();wc

10、obj.processFile();/.如果程序规模很小,采用第一种方式较精简,若程序有一定规模,涉及到多个类,则用第二种方式更好第9页/共44页第8页/共44页u 数据成员术语上称为字段,用来表征对象的或整个类的状态或信息(以后把数据成员都称作字段)u 如何确定对象(类)所需的字段呢?可从两方面考虑一、对象与外界交流的信息,包括:对象实现其功能所需的外部信息,这往往在对象创建时需要明确(例如一个WordCount实例接受统计任务的文本文件、可选参数选项等);需要向外界提供的信息。这些设置类字段的首要依据二、对象执行其功能的过程中需要保持的状态,这些状态对多个成员函数有影响(例如WordCou

11、nt中,需要保存文本行串的ArrayList对象,由readFile()函数写入内容,而后又被countWords()函数访问)这类数据的设置与C+中全局变量的作用相似u确定字段时,应同时明确其类型;u字段的访问级别 字段访问级别一般都应设为private,以防范类对象的状态和信息被随意修改(后面介绍属性成员,可让字段被外界访问 并能在受监控情况下被修改)2.2 数据成员第10页/共44页第9页/共44页u 以下是WordCount class 的字段的设置(请根据WordCount的功能,仔细思考各字段设立的理由)public class WordCountprivate bool m_sp

12、y;/是否要统计执行时间private bool m_trace;/是否要跟踪执行过程private string m_file_name;private string m_file_output;private StreamReader m_reader;private StreamWriter m_writer;private ArrayList m_text;private Hashtable m_words;private string m_sentences;/.第11页/共44页第10页/共44页u信息隐藏与类的可修改性类发布后,参与到程序开发中,使用类的过程中,不可避免会有修改需

13、求举个例:WordCount 类设置跟踪选项,体现于字段 m_trace上,m_trace最初定为bool型,值为true时开启跟踪并输出到屏幕。但使用后,用户可能会发现,处理大文件时,屏幕输出的内容太多太快,来不及阅读。进而希望能把跟踪结果输出到文件中,以便以后打开阅读。现在为支持三种跟踪设置(不跟踪、输出到屏幕以及输出到文件),就需要改变m_trace的类型,可用整型,约定:0代表不跟踪,1代表输出屏幕,2代表输出文件以后还可能需要更多选择(这时使用枚举enum类型更有效)类应如何设计以提高可修改性?理想的可修改性是:类可自由修改,对使用该类的已有程序毫无影响将字段设定为public,使程

14、序能直接访问数据成员的做法将会严重影响类的可修改性(这样导致紧耦合)要提高类代码的可修改性,需要信息隐藏(代码设计上就是把成员访问级别设为private)2.3 属性(Properties)第12页/共44页第11页/共44页u把字段设置为private是标准做法,但有些字段记录的信息需要提供给外界,例如:字串的长度信息,一个ArrayList对象含有的元素个数。WordCount例子中已指出解决方法属性u属性(property)是一种特殊的成员函数属性定义的格式为:访问级别 类型 属性名称get .return.;/读访问器set .=value;/写访问器第13页/共44页第12页/共44

15、页 属性是提供外界访问内部数据的接口,所以访问级别一般是public(若用作private就失去意义)属性与某个字段关联,提供对此字段的访问操作,并可控制访问该字段的能力可读/写,当同时提供get/set访问器只读,只提供get访问器只写,只提供set访问器属性的类型与所关联的字段类型可以相同也可以不同属性的类型决定了信息的外部表达方式(例如字段为日期型,通过属性对外表达为字符串类型)当属性类型与关联的字段类型相同时,get访问器的最简实现方式是直接传回该字段;set访问器的最简单实现方式是直接把传入的value赋予关联的字段get 和set访问器还可独立声明访问级别(当需要与整个属性的访问级

16、别不同时),这称为非对称访问器(实际使用中,主要是把set访问器设为protected级别)u注意属性与函数定义上的差别(属性不带圆括号,函数要带)u对属性的访问操作与访问public字段基本相同(除一些特殊场合外,如作为函数引用传递方式的参数不可使用属性)第14页/共44页第13页/共44页u索引器能让类对象带有类似数组一样的下标访问功能u当类对象包含集合型的字段时,建立索引器来访问这类字段的元素显得很直观自然:例如,要获取WordCount的实例wcobj 执行统计操作的结果,利用索引器设置,以下标操作方式取回某单词出现的次数:int count=wcobj“apple”;u 索引器的定义

17、与属性定义非常像,差别仅是:名称必须是this且带有 的定义u 中至少包含一个下标的类型及名称(就像定义函数参数一样),下标的类型并不局限于整型下面是WordCount对象的索引器定义:2.4 索引器(Indexers)第15页/共44页第14页/共44页public class WordCountprivate Hashtable m_words;/集合型的字段 /.public int this string idx get if(idx.Length=0)throw new ArgumentException();/抛出异常 if(m_words=null)throw new Excep

18、tion();/抛出异常 return(int)m_wordsidx;/.第16页/共44页第15页/共44页u变量被使用前必须先赋值(初始化)u字段的初始化与局部变量初始化的差异之处u字段初始化的时机:若无特定的初始化要求,系统按类型默认值自动初始化类的设计者确定初始值在声明字段的同时提供初值进行初始化编写构造函数,在构造函数中对字段赋值/推荐这种类的使用者确定初始值先构建对象,再通过public属性对字段赋值(即两步操作)构建对象的同时,直接向对象构建器(构造函数)提供字段的初值(一步操作)2.5 字段的初始化、构造函数第17页/共44页第16页/共44页u默认构造函数u构造函数的定义构造

19、函数与类同名,且不需指定类型构造函数可以重载,通过不同参数定义来区分构造函数的访问级别静态构造函数u构造函数是否应提供,提供多少个?一旦定义构造函数,编辑器将不再提供默认构造函数例子:单词统计器要求用户提供文件名,此外用户还可以要求开启一些选项,因此为WordCount类定义相应构造函数是较佳的做法public WordCount(string file_name).public WordCount(string file_name,bool spy,traceFlags trace).u构造函数间的调用语法 this()public WordCount(string file_name):t

20、his(file_name,false,traceflags.turnoff).u构造函数定义策略第18页/共44页第17页/共44页 练习:设计Point3D class 的构造器,让用户在创建一个Point3D对象(这个对象可能代表一个三维点、或平移量、坐标偏移或不确定的三维变换要素)时,能够选择用传入3个、2个、1个或者不给任何坐标值的方式创建,例如:Point3D origin=new Point3D();/无坐标提供,则生成默认原点Point3D x_offset=new Point3D(1.0);/则生成x轴平移(1.0,0,0)Point3D translate=new Poin

21、t3D(1.0,1.0);/生成平移变换(1.0,1.0,0)Point3D mumble=new Point3D(1.0,1.0,1.0);/生成点(1.0,1.0,1.0)class Point3D double x,y,z;public Point3D(double v1,double v2,double v3)x=v1;y=v2;z=v3;/请补充构造函数,以满足上述对象创建要求 .第19页/共44页第18页/共44页u类各个实例拥有各自的存储空间,以保证实例数据独立u不同实例的实例成员函数是否也需要独立的存储空间?答案是不需要,所有实例共享一份实例成员函数的代码 但一份实例成员函数代

22、码如何正确访问各个实例字段?u隐含this 引用的绑定工作编译器对代码中涉及的实例字段加以扩展:添加this引用如:m_sentences=new stringm_text.Count;扩展为this.m_sentences=new stringthis.m_text.Count;对实例函数的调用代码则重写,例如:theObj.processFile();重写为processFile(theObj);对函数定义:public void processFile()countWords();重写为 public void processFile(WordCount this)this.countW

23、ords();进一步重写为public void processFile(WordCount this)countWords(this);2.6 实例函数对实例成员的访问,this 引用 第20页/共44页第19页/共44页u对象都对应着一个隐含的this引用,其中放着对象的地址uthis引用的妙用一个双向链表的例子class StringNodeprivate StringNode back_link;/后向指针private StringNode front_link;/前向指针private string text;public StringNode(string str)text=st

24、r;/考虑增设一个 Insert()成员函数,以在当前的对象前插入新结点 public void Insert(StringNode new_node)new_node.front_link=front_link;/?front_link=new_node;new_node.back_link=?;第21页/共44页第20页/共44页u静态成员用于表现属于整个类的特征和行为(例如C#的整数类的最大最小值。还有哪些例子?请举出)u对静态成员的访问在class定义范围内,对静态成员的访问与实例成员一样在class定义的范围外,则需要通过类名直接访问静态成员(必须是public),通过类的具体实例来

25、访问该类的静态成员是语法错误u静态字段的初始化默认初值在声明中直接指定初值若想通过构造函数初始化静态成员,则要用静态构造函数u对静态字段的封装原则与实例字段一样2.7 静态(static)成员第22页/共44页第21页/共44页u const 字段 是一种常变量(符号常量),必须在声明时赋值,之后不可再修改,编译器会对const字段进行编译期评估并做优化除了string类型,其他引用类型都不能够定义为const字段。原因在于,除string外的引用类型要使用new操作才可分配,而new操作执行于运行期,与编译器对const字段的处理矛盾const字段隐含是static的,在类外要通过类名访问。

26、ureadonly字段 可在运行期(例如在构造函数中进行赋值)初始化,如此一来,当需要不可修改的引用型字段时,可以用静态readonly字段来模拟const字段2.8 const 和readonly 字段第23页/共44页第22页/共44页u 所谓enum类型 是定义了由一组互有关联的具名整型常量,本质上是整数,因此属于值类型声明语法:访问级别 enum 枚举名称:载体整数类型枚举元名称1=N1,枚举元名称2=N2,.,枚举元名称t=Nt;其中枚举元名称要唯一,多个枚举元可以用同一个整数值在枚举定义外对枚举元访问格式是:枚举名.枚举元名若枚举定义嵌套于一个类的定义中,则在该类外对此枚举元访问的

27、格式为:类名.枚举名.枚举元名虽然enum本质上是整型,但要用显式写法与整数互相转型enum型支持以递增递减的操作(+,-)遍历枚举元组enum的好处是:可以提供清晰选项,而又具备类型安全检查,逻辑上能预防不合法值的输入2.9 枚举(enum)类型的运用第24页/共44页第23页/共44页 举例public class WordCountpublic enum traceFlags turnOff,toConsole,toFile;private traceFlags m_trace;.public class Entr ypointstatic public void Main(string

28、 args)WordCount.traceFlags traceOn=WordCount.traceFlags.turnOff;.foreach(string option in args)switch(option)case”-t”:traceOn=WordCount.traceFlags.toConsole;break;case”-tf”:traceOn=WordCount.traceFlags.toFile;break;./.程序接下来,将把traceOn作为 参数创建一个WordCount 的对象实例,更详细的示例参看C#primerP85页第25页/共44页第24页/共44页u 委托

29、类型是一种指向函数体的引用型别,或者可以理解为一种能代表某类函数(以函数返回型及参数列 分类)的特殊的类;通过操纵委托类型对象,可以操纵其代表的函数(与C+的函数指针概念类似)delegate 对象可同时代表(指向)多个函数,当该对象被调用时(就像调用普通的函数),它所代表的函数将按被代表的先后顺序逐一执行delegate对象可代表来自不同class的成员函数(静态非静态都可以),前提是这些函数具有该delegate类型要求的函数返回型和参数标记声明delegate型,事实上是在定义类派生自抽象基类Delegate或MulticastDelegate 的子类udelegate定义语法:访问级别

30、 ;2.10 委托(delegate)型第26页/共44页第25页/共44页例如:public delegate void Action();/这句定义了一个名为 Action 的 delegate ,这种delegate能够/代表 无参数无返回值的函数 可以用这个Action delegate声明一个对象引用(handle):Action theAction;/这句声明了一个Action型的引用型变量,名为 theAction与其他引用类型一样,需要用new操作来创建Action 实例 并将内存地址赋予Action型的引用变量(称为函数注册操作)theAction=new Action(An

31、nounce.AnnounceDate);/上句中的 Announce.AnnounceDate 是 类Announce的static函数/AnnounceDate()的全局名称,该函数无参数无返回值若Announce类有实例函数 announceTime,也是无参数无返回值,假定an已被创建为Announce类的实例handle,则可有theAction=new Action(an.announceTime);/这是一个非静态函数的注册第27页/共44页第26页/共44页 Announce类的定义:public class Announcepublic static void announc

32、eDate()DateTime dt=DateTime.Now;Console.WriteLine(“Todays date is 0”,dt.ToLongDateString();public void announceTime()DateTime dt=DateTime.Now;Console.WriteLine(“The current time is 0”,dt.ToShortTimeString();第28页/共44页第27页/共44页u创建了delegate 对象实例后,就可以用call操作符圆括号(),调用该对象实例所代表的函数:theAction();/此句将调用注册于theA

33、ction上的函数 若theAction从未进行过注册操作,则theAction=null,当然就不代表任何函数,上句就会引起异常。因此健壮的代码应该在call操作前作判断:if(theAction!=null)theAction();u当某个delegate型对应于无返回值的函数类型时,这个delegate型的实例将能代表多个函数,当进行call操作时,将按注册顺序依次执行所代表的这些函数,可以用+=和-=进行多函数的注册操作或注销操作u更详细的内容请参阅C#primer (p86页 2.12节)udelegate是实现事件编程的关键,类的事件实际上就是某种delegate类型第29页/共4

34、4页第28页/共44页u通常,函数的参数可看作该函数的局部变量,这种局部变量的初始化是在函数被调用时绑定由外界传入的数值来完成定义函数时,参数声明于圆括号内,需指明参数的类型和名称,有多个参数时,以逗号分隔,并且每个参数都应独立指明其类型(不能有压缩的写法,如 f(int i,j)是语法错误)参数的可见性,规则与一般局部变量相同当外部调用函数时,函数的参数术语上称为“形参”,而传入的外部变量(或表达式、常量值)称为“实参”u外部传入变量时函数形参与实参的绑定(或者说实参传递给形参)有两种方式默认是“值传递”方式:为形参分配独立存储空间存放实参值“引用传递”方式:不分配存储空间,而以别名的方式直

35、接访问(使用)实参值C#语言中,要以ref 或out 关键字 指明参数传递采用“引用传递”方式(在函数定义中 及调用时,均需带有这种关键字)2.11 函数的参数传递第30页/共44页第29页/共44页u值传递方式的使用 值传递方式中,实参变量与形参变量相互独立,函数对形参的任何修改都不会影响实参需要特别注意的是引用类型的形参采用值传递方式的情况,这种情况下,形参获得独立内存分配并存储实参的值这个值只是一个handle,即实际对象的内存地址请分析以下例子:static public void byValue(string s)Console.WriteLine(“original input,s

36、:0”,s);s=s.ToUpper();Console.WriteLine(“after modify,s is:0”,s);static public void Main()string s=“abcde”;Console.WriteLine(“original s:0”,s);byValue(s);Console.WriteLine(“now,after call byValue(),s is:0”,s);第31页/共44页第30页/共44页u 引用传递方式的使用如果希望函数对形参的修改能反映到实参变量上,就应该采用“引用传递”方式通过关键字ref修饰,就可以通知编译器以引用传递方式处理

37、参数对前面例子稍作修改,请再分析:static public void byRef(ref string s)Console.WriteLine(“original input,s:0”,s);s=s.ToUpper();Console.WriteLine(“after modify,s is:0”,s);static public void Main()string s=“abcde”;Console.WriteLine(“original s:0”,s);byRef(ref s);Console.WriteLine(“now,after call byRef(),s is:0”,s);第3

38、2页/共44页第31页/共44页out关键字修饰的参数是引用传递方式的另一种情况通常作为实参传入的变量都要求已被赋值。有时只是想调用函数以获得某种计算结果,以ref参数传入可满足此要求,但却要先赋一个无甚意义的初值。C#提供out关键字,以表明传入的参数将在函数运行期间赋值,从而只需在外部声明一个变量,无需赋值就可直接作为out参数传给函数。编译器亦会严格检查函数中是否为此out参数赋值,若未有赋值操作则视为语法错误out 方式仍是一种引用传递方式,注意与ref的区别参数以引用传递传入的ref或out声明,在定义函数和调用函数时都要提供uref,out关键字会参与到函数的重载判决中,因而增加了

39、编程的灵活性第33页/共44页第32页/共44页u 两个及以上的函数共用同一个名称只要每个函数的参数列(在参数类型和参数个数上)独一无二,这称为函数重载函数重载机制,使具有类似操作但要各自实现的函数能以名称归为一组,从而简化编程。函数重载机制可以理解为静态多态性:执行同名函数的哪一个,在编译阶段确定。(与之对应的是动态多态性:在运行阶段才确定调用哪个函数)u重载函数的决议编译器依赖函数参数列表(而非函数的返回类型)作决议当分析函数的调用函数语句时,编译器将实参与各重载函数的参数列进行比较,从而选出最佳匹配,整个过程分三步:确认候选函数通过函数名称找出重载函数集选出可行函数候选集中具有与实参吻合

40、的参数列的函数选出最佳匹配可行集中选出最佳可行函数2.12 函数重载第34页/共44页第33页/共44页例,有以下函数定义void f(int i1,int i2)./(1)void f(float f1,float f2)./(2)void f(string s)./(3)现在以两个整数为参数调用f()f(1024,2048);编辑器判决过程:1.候选函数集包括上述定义的(1)(2)(3)号函数2.可行函数集包括(1)和(2)(1)的参数完全匹配,而两个整数实参可通过隐式转换为(2)要求的两个浮点类型)3.最佳匹配是(1),完全匹配当然优于需要转换若不存在完全匹配,又当如何?int ival

41、;long lval;short sval;/.f(ival,lval);/用哪个?f(ival,sval);/用哪个?第35页/共44页第34页/共44页u 最佳匹配的确定可行函数的形参个数与调用传入的实参个数必须完全相等;实参与对应的形参类型不同时,必须能隐式转换为形参的类型(但对于ref与out参数 则不考虑转换 必须完全匹配)当可行函数集中的函数均不是完全匹配(即都需要转换时)按以下规则确定较佳者如果类型T1能隐式转换为T2,而反向的隐式转换不存在,则类型S转换为T1就优于S转换为T2这条规则意味着“最容易达到的转换,就是首选的转换”即使有了上述规则,在多参数的情形下,最佳匹配的判决也

42、可能中途而止,并导致编译错误:void g(long l,float f).void g(int i,double d).g(0,0);/这个重载决议将引发“歧义”的编译错误/这时需要程序员作出决定 将实参显式转换:g(0,(double)0);第36页/共44页第35页/共44页uC#函数有一种特殊的参数定义可变长参数,能够接收任意个数的参数输入(有些相似的函数操作可能要接受个数不同的参数,通过定义一组具有不同个数参数的重载函数组,通常就能解决问题;但若情况复杂得需要写数量众多的重载函数来满足参数个数的要求,则可考虑使用可变长参数)u可变长参数 以关键字 params 后跟一个一维数组的声明

43、来指定:static void func(params int args).uparams参数只可有一个,如果函数还有其他个体参数,则params参数必须放在最后声明:static void func(string msg,int ix,params object args).u带有params参数的函数如何参与到重载函数决议中?请自行上机实验,找出答案 2.13 可变长参数列第37页/共44页第36页/共44页u 运算符重载是一种特殊的函数重载,主要作用是为C#内建的运算符提供与自定义的类型 相适应的运算实现例如,可以为矩阵类定义数乘运算public class Matrixpublic s

44、tatic Matrix operator*(Matrix mat,double dval)Matrix result=new Matrix(mat.rows,mat.cols);for(int ix=0;ix mat.rows;ix+)for(int iy=0;iymat.cols;iy+)resultix,iy=matix,iy*dval;return result;/.Matrix class 的其余定义内容2.14 运算符重载第38页/共44页第37页/共44页u运算符重载语法要点运算符重载定义在 要提供特定运算的类中必须声明为public 和static,重载的运算符以operato

45、r关键字引出,参数至少包含一个本类的实例被重载的运算符操作的参数不能是ref或out形式的运算符重载后 复式运算自动支持(如+=,*=等)u并非所有的运算符都能被重载,关于运算符重载更详细的信息可参考C#Primer(P107-P110页)第39页/共44页第38页/共44页u类型转换操作可以为自定义的类提供显式或隐式的转换操作u类型转换定义也是一种特殊的函数重载 这部分内容较为少用,此处从略。更详细内容可参阅C#primer(P110-P112页)u类型间的转换除了显式和隐式转换外,还有其他途径:字串到数值的转换,用目标数值类型的 Parse()方法,如:int.Parse(“100”);/

46、将子串“100”转换为整数100利用 System.Convert 类的各个转换函数 2.15 类型转换操作第40页/共44页第39页/共44页u析构函数用于一些善后工作的处理,比如关闭一些文件对象u由于C#的垃圾回收机制,通常并不需要析构函数(也不鼓励用)u对于文件,数据库连接等资源的释放,可以采用另外更好手段u如果非要使用析构函数,以下是一些语法要点名称为类名无返回类型声明,无参数,因而不能重载2.16 析构函数第41页/共44页第40页/共44页u结构struct与class除了关键字不同外,似乎没有分别,但两者使用还是有区别的struct不能从其他struct或class派生,本身也不

47、可被继承struct是值型,而class是引用型。这意味着将一个struct型变量赋予另一个时,发生的是深拷贝struct型变量不在托管堆中分配内存,因而不受垃圾回收器的支配struct不能自定义无参数的构造函数(由系统自动提供),但可以定义带参数的构造函数struct的成员声明时不可进行初始化赋值struct不能定义析构函数u使用struct来代替class的主要原因是在一些情形下会比class有更高的运行性能2.17 结构(struct)型的使用第42页/共44页第41页/共44页一个例子struct point public int x,y;/注意,结构的成员不能赋初值class Tes

48、tstatic void Main()point P1;/P1.x=166;/若point是一个类,这里会报错,为什么?P1.y=111;point P2;P2=P1;point P3=new point();第43页/共44页第42页/共44页2.18 小结u类的设计、类的成员种类静态成员和实例成员,static修饰,this引用数据成员和函数成员数据成员:字段,事件(委托类型)函数成员:方法,属性,运算符,索引器,构造器,终结器u构造函数和析构函数uconst 和readonly字段u函数(方法)的参数重载判决参数传递方式u其他类型枚举(enum)委托(delegate)结构型(struct)第44页/共44页第43页/共44页感谢您的欣赏!第44页/共44页

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > PPT文档

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁