第4章 面向对象编程进阶
第四章.面向对象编程进阶
一.选择题
1.委托声明的关键字是_A______。
A.delegate
B.s ealed
C.o perator
D.event
2.声明一个委托“public delegate intmyCallBack(sring s);”,则用该委托产生的回调方法的原型应该是__A_____。
A.void myCallBack(sring s);
B.int receive(string str);
C. string receive(string s);
D.不确定;
3.在C#中,有关事件定义正确的是__B_____。
A. public delegate void Click;
public event Click Onclick;
B.public delegate void Click();
public event Click Onclick();
C. public delegate Click;
public event Click Onclick;
D. public delegate void Click();
public event Click Onclick;
4.接口可以包含一个和多个成员,以下选项___D__不能包含在接口中。
A.方法、属性
B.索引器
C.事件
D.常量
5.下列叙述中,正确的是__B__。
A.接口中可以有虚方法
B.一个类可以实现多个接口
C.接口能被实例化
D.接口中可以包含已实现的方法
一.问答题
1.举一个现实世界中继承的例子,用类的层次图表现出来。
2.什么是抽象类和密封类?他们有什么不同?
解:密封类就是在类声明是用一个关键字sealed,密封方法也一样。密封了的类不能在被继承,密封的方法不能再重写。
抽象类不能实例化,可以继承。有抽象方法的类一定是抽象类。抽象方法必须在派生类中重写。
3.什么情况下使用隐式数值转换和显式数值转换?
解:隐式转换不需要在代码中指定转换类型,例如:intintNumber = 10;double doubleNumber = intNumber;intNumber会被隐式转换成double类型。显式转换则相反,需要指定转换类型,例如:double doubleNumber = 10.1;int intNumber = (int)doubleNumber;
对于表示数值的基本数据类型来说,数值范围小的数据类型转换成数值范围大的数据类型可以进行隐式转换,而反过来则必须进行显示转换。就像上面的两个例子一样。对于类类型来说,子类转换成父类可以进行隐式转换,而反过来则必须进行显式转换,例如:string str1 = "abc";object obj = str1; //子类转换成父类,隐式转换string str2 = (string)obj;
//父类转换成子类,显式转换如果两个类之间没有继承关系,则不能进行隐式转换或显式转换,此时必须在被转换的类中定义一个隐式转换方法或显式转换方法
4.集合的使用有哪两种方式?举例说明。
List 泛型强类型列表,可以通过索引访问,内部是数组实现
Dictionary 泛型强类型字典,表示键值对的集合,使用键访问,内部是哈希表实现
Stack 栈,后进先出集合
Queue 队列,先进先出集合
最常用的就是上面几个
其他的还有LinkedList(双向链表),HashSet, SortedList等
还有各自的非泛型版本,比如List对应的ArrayList,Dictionary对应的HashTable,还有Queue对应的Queue,这些都已过时,建议不要再用
5.C#语言引入委托机制的目的是什么?为什么说委托是”C#比别的OO语言更加彻底贯彻
面向对象思想的绝佳体验之一“?
平常我们的方法或者函数只能用来传参数,有的时候一个方法可能需要另一个方法的支持,所以我们可以定义个委托来传这个方法。
需要注意的是,委托和你所要传的方法的返回值类型要一致。
6.是列举几种常见的预处理命令以及使用方法。
在C# 中没有单独的预处理步骤;预处理指令按词法分析阶段的一部分处理。预处理指令既不是标记,也不是C# 句法文法的组成部分。但是,可以用预处理指令包含或排除标记序列,并且可以以这种方式影响C# 程序的含义。
7.什么是程序集?它的作用有哪些?
1.程序集是一个或多个托管模块,以及一些资源文件的逻辑组合。
2.程序集是组件复用,以及实施安全策略和版本策略的最小单位。
3.程序集是包含一个或者多个类型定义文件和资源文件的集合。在程序集包含的所
有文件中,有一个文件用于保存清单。(清单是元数据部分
中一组数据表的集合,其中包含了程序集中一部分文件的名称,描述了程序集的版本,语言文化,发布者,共有导出类型,以及组成该程序集
的所有文件)。作为一个单元进行版本控制和部署的一个或多个文件的集合。程序集是.NET Framework 应用程序的主要构造块。所有托管
类型和资源都包含在某个程序集内,并被标记为只能在该程序集的内部访问,或者被标记为可以从其他程序集中的代码访问。程序集在安全方
面也起着重要作用。代码访问安全系统使用程序集信息来确定为程序集中的代码授予的权限集。程序集是.NET Framework 编程的基本组成部分。
8.泛型是什么?有何作用?
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。
泛型的定义主要有以下两种:
1.在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,
不能代表个别对象。(这是当今较常见的定义)
2.在程序编码中一些包含参数的类。其参数可以代表类或对象等等。(人们大多把这
称作模板)不论使用哪个定义,泛型的参数在真正使用泛型时都必须作出指明。
9.下面的程序,输入不同参数,分析运行结果。
如分别输入:test5, test ,test hello, test 0, test 12121212121212
using System ;
class Test;
{
public static void Main ( string[] args)
{
try
{
int I = 10/int32.parse(args[ 0] );
}
catch ( IndexOutOfRangeExcept e)
` {
Console.WriteLine(e.Message);
}
cathh ( FormatException e)
{
Console.writeLine(e.Message);
}
Catch ( DivideByZeroException e)
{
Console.WriteLine( e.Message);
}
Catch ( OverflowException e)
{
Console.writeLine(e.Message );
}
}
}
10.指出下面代码错误的地方并进行修改。
usingSystem;
namespace PavelTsekov
{
interface I1
{
void MyFunction1();
}
interface I2
{
void MyFunction2 ();
}
class Test : I1, I2
{
public void I1.MyFunction1()
{
Console.WriteLine(“ Now I can say this here is I1 implement!”) }
public void I2.MyFunction2();l
{
Console.WtiteLine(“ Now I can say this here is I2 implement!”);
}
classAppClass
{
public static void Main( string[] args)
{
Test t = new Test ();
t.MyFunction1();
t.MyFunction2();
}
}
` }
11.分析下面代码,指出Digit和byte之间的转换方式,原因是什么?
using System;
publicstruct Digit;
{
byte value;
public Digit (byte value)
{
if (value < 0 | | value > 9 )
thow new ArgumentException();
this.value = value;
}
public static implicit operator byte (Digit d)
{
returnd.value;
}
public static explicit operator Digit(byte b)
{
return new Digut(b);
}
}
三.编程题
1.利用抽象类和虚方法设计一个信用卡通用付账系统。系统可以使用3个银行的信用卡,其中两个是跨地区的银行,一个是本地银行。跨地区的银行提供的信用卡又分为3种:本地卡、外地卡、通存通兑卡。系统不处理外地卡付账。实现的功能有:付账、查询、转账、取款。
2.定义一个复数类,通过重载运算符:=、+= 、+、-、*、/ ,直接实现两个复数之间的各种运算。编写一个完整的程序。(包括测试各种运算符的程序部分)。
提示:两复数相乘的公式为:(a+bi)*(c+di) =(ac-bd)+(ad+bc)i,而两个复数相除的计算公式为:(a+bi)/(c+di)=(ac+bd)/(c*c+d*d)+(bc-ad)/(c*c+d*d)i;
class Complex
{
public double real;
public double imaginary;
public Complex(double real, double imaginary) //构造函数
{
this.real = real;
this.imaginary = imaginary;
}
//声明重载运算符(+),将两个复数对象相加,返回复数类型
public static Complex operator + (Complex c1, Complex c2)
{
return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
//声明重载运算符(-),将两个复数对象相减,返回复数类型
public static Complex operator - (Complex c1, Complex c2)
{
return new Complex(c1.real - c2.real, c1.imaginary - c2.imaginary);
}
//声明重载运算符(*),将两个复数对象相乘,返回复数类型
public static Complex operator * (Complex c1, Complex c2)
{
return new Complex(c1.real * c2.real - c1.imaginary * c2.imaginary , c1.real *c2.imaginary + c1.imaginary * c2.real);
}
//声明重载运算符(/),将两个复数对象相除,返回复数类型
public static Complex operator / (Complex c1, Complex c2)
{
double cd = c2.real * c2.real + c2.imaginary * c2.imaginary ;
return new Complex((c1.real * c2.real + c1.imaginary * c2.imaginary) / cd, (c1.imaginary * c2.real -c1.real*c2.imaginary)/cd);
}
//重载ToString() 方法,以传统格式显示复数
public override string ToString()
{
return (String.Format("{0} + {1}i", real, imaginary));
}
}
classTestComplex
{
static void Main()
{
Complex num1 = new Complex(2, 3);
Complex num2 = new Complex(3, 4);
Complex sum = num1 + num2; //重载加运算符添加复数对象
Complex sub = num1 - num2; //重载减运算符添加复数对象
Complex multiplication = num1 * num2; //重载减运算符添加复数对象
Complex division = num1 / num2; //重载减运算符添加复数对象
//重载ToString方法输出复数的加减乘除
Console.WriteLine("第一个复数: {0}", num1);
Console.WriteLine("第二个复数: {0}", num2);
Console.WriteLine("复数和: {0}", sum);
Console.WriteLine("复数差: {0}", sub);
Console.WriteLine("复数积: {0}", multiplication);
Console.WriteLine("复数商: {0}", division);
}
}
3.定义一个学生类,数据成员包括:姓名,学号、C++、英语和数学成绩。重载运算符“<<”和“>>”,实现学生类对象的直接输入和输出。
4.定义一个平面直角坐标系傻瓜的一个点的类CPoint,重载“++”和“——”运算符,并区分这两种运算符的前置和后置运算,构造一个完整的程序。
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Crectrect = new Crect() { X = 1, X2 = 2, Y = 0, Y2 = 1 };
Console.WriteLine(rect.Length);
Console.WriteLine(rect.Perimeter);
Console.WriteLine(rect.Area);
}
}
internal class Cpoint
{
public double X { get; set; }
public double Y { get; set; }
}
internal class Cline : Cpoint
{
public double X2 { get; set; }
public double Y2 { get; set; }
public double Length
{
get
{
returnMath.Sqrt(Math.Pow(Math.Abs(X2 - X), 2.0) + Math.Pow(Math.Abs(Y2 - Y), 2.0)); }
}
}
internal class Crect : Cline
{
public double Perimeter
{
get
{
return 2 * (Math.Abs(X2 - X) + Math.Abs(Y2 - Y));
}
}
public double Area
{
get
{
returnMath.Abs(X2 - X) * Math.Abs(Y2 - Y);
}
}
}
}