面向对象测试题

  • 格式:doc
  • 大小:59.00 KB
  • 文档页数:9

一、问答题

1. 值类型和引用类型的区别?

值类型和引用类型的区别在于,值类型的变量直接存放实际的数据,而引用类型的变量存放的则是数据的地址,即对象的引用。

值类型变量直接把变量的值保存在栈中,引用类型的变量把实际数据的地址保存在栈中,而实际数据则保存在堆中。

注意,堆和栈是两个不同的概念,在内存中的存储位置也不相同。

堆(Heap)一般用于存储可变长度的数据,如字符串类型堆中保存值和对象,调用完毕之后依然存在,由垃圾回收器查找栈中有无指向该值或对象的引用,无则从堆中删除;

栈(Stack)则用于存储固定长度的数据,如整型类型的数据int(每个int变量占用四个字节),栈由系统管理生存期,存储代码执行和调用路径,执行或调用完毕即从栈中清除。

由数据存储的位置可以得知,当把一个值变量赋给另一个值变量时,会在堆栈中保存两个完全相同的值;

而把一个引用变量赋给另一个引用变量,则会在堆栈中保存对同一个堆位置的两个引用,即在堆栈中保存的是同一个堆的地址。

在进行数据操作时,对于值类型,由于每个变量都有自己的值,因此对一个变量的操作不会影响到其它变量;

对于引用类型的变量,对一个变量的数据进行操作就是对这个变量在堆中的数据进行操作,如果两个引用类型的变量引用同一个对象,实际含义就是它们在堆栈中保存的堆的地址相同,因此对一个变量的操作就会影响到引用同一个对象的另一个变量。

(1) 值类型

包括:简单类型、结构类型、枚举类型。其中,简单类型又分为:整型、布尔型、字符型、浮点型、小数型。

(2) 引用类型

包括:对象类型、类类型、接口、元数据、字符串类型、数组。

//值类型与引用类型的例子

static void Main(string[] args)

{

//=====值类型,操作的是值========

int i1 = 10;

int i2 = i1;

i2 = 88;

Console.WriteLine(i1 + " " + i2);

//10 88 [由于值类型直接操作值,所以不会发生改变]

//=====引用类型,操作的是引用,所谓的引用可以看作是指向内存的地址,地址再对应着内容=====

int[] intArr1 = new int[] { 1, 2, 3 };

int[] intArr2 = intArr1;

intArr2[0] = 9;

intArr2[2] = 0; foreach (int i in intArr1)

{

Console.Write(i);

//结果:920

[由于引用类型intArr1的引用赋值给了intArr2,所以他们是持有同一个引用,当intArr2的引用发生改变的时候,intArr1的引用也将发生变化]

}

foreach (int j in intArr2)

{

Console.Write(j);//结果:9 2 0

}

Console.Read();

下面代码的输出结果是什么?

class Program

{

static void Main(string[] args)

{

string b;

b = "old";

Func1(ref b);

Console.WriteLine(b);

int c;

c = 3;

Func1(ref c);

Console.WriteLine( c);

}

public static void Func1(ref string a)

{

a = "new";

}

public static void Func1(ref int a)

{

a = 6;

}

}

答案:

new 6

题目2:下面代码的输出结果是什么?

class Program

{

static void Main(string[] args)

{

string b;

b = "old";

Func1( b);

Console.WriteLine(b);

int c;

c = 3;

Func1( c);

Console.WriteLine( c);

}

public static void Func1( string a)

{

a = "new";

}

public static void Func1( int a)

{

a = 6;

}

}

答案:

old

3

2. 简述装箱和拆箱的过程。

装箱(boxing)是将值类型隐式地转换为引用类型。如int i=3; object o = i ;便是装箱过程,装箱一个数值会为其分配一个对象实例,并把该数值拷贝到新对象中。拆箱(unboxing)是显式地把引用类型转换成值类型,如int j = (int)o char j= (char)o。

3. 结构和类的区别是什么?

1) 结构是一个值类型,保存在栈上,而类是一个引用类型,保存在受管制的堆上。

2) 对结构中的数据进行操作比对类或对象中的数据进行操作速度要快。

3) 一般用结构存储多种类型的数据,当创建一个很多类或对象共用的小型对象时,使用结构效率更高。

4. 什么是静态变量? 类的数据成员可以分静态变量、非静态变量两种.

静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.

非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中。

一个类中可以同时包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数。

5. abstract class和interface有什么区别?

声明方法的存在而不去实现它的类被叫做抽像类(abstract class),它用于要创建一个体现某些基本行为的类,抽象类不能被实例化。

abstact class A

{}

A a = new A(); //这个是错误的

class B:A

{}

B b = new B();

A a = b;

-------------------

然而可以创建一个变量,其类型是一个抽像类,

并让它指向【具体子类】的一个实例。

-------------------

===》不能有抽像构造函数或抽像静态方法。

抽象类的方法必须全部被子类继承::如果子类也是抽象的,那么就不必全部继承

接口(interface)是抽像类的【变体】。

在接口中,所有方法都是抽像的;在抽象类中,有些方法可以不是抽象的。

多继承性可通过接口实现。

接口中的所有方法都是抽像的,没有一个有【方法体】。

interface A

{}

interface B

{}

abstract class A1()

{}

abstract class A2

{}

class c:A1,A,B

{}

6. 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? 接口可以继承接口。抽象类可以实现(implements)接口,

抽象类是可继承实体类,

但前提是实体类必须有明确的构造函数。

7. 进程和线程分别怎么理解?

1)定义解释

进程是具有一定独立功能程序在关于某个数据集上的一次运行活动。进程是系统进行资源分配和调度的一个独立单位。

线程是进程的一个实体,是Cup调度的基本单位。它是比进程更小的能独立运行的基本单位,线程只拥有一点在运行中必不可少的资源,可与同一个进程中其他线程共享进程中所拥有的所有资源。一个线程可以创建和销毁另一个线程,同一进程中的多个线程可以同时并发执行;

2)区别解释

一个程序至少有一个进程,一个进程至少有一个线程。

线程的划分尺度小于进程,使得多线程程序并发行高,另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存从而极大的提高程序的运行效率。

进程有独立的地址空间一个进程崩溃后在保护模式下不会对其他进程产生影响,而线程只是一个进程中的不同执行路径;线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。所以多进程的程序要比多线程的程序健壮,但在进程切换时耗费资源较大,效率要差一些。但对一些要同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

8. 简述“开-闭”原则的基本思想。请举出一个使用了软件“开-闭”原则的软件设计模式,其中何处体现了“开-闭”原则。

答:“开—闭”原则:软件实体应当对扩展开放,而对修改关闭,“开-闭”原则要求软件系统能够在不需要修改原有类的基础上,通过增加类达到扩展功能的目的。

Abstract factory体现了这个原则,如果想增加一类新的products,只需在product类体系中增加各个products,然后在factory类体系结构中增加一个concrete factory就可以了,而不需要对现有类做任何修改,The Open-closed principle[ocp]在不改动过模块源代码的情况下扩展模块的行为。

9. 简述依赖倒置原则的基本思想。请举出一个使用了软件依赖原则的软件设计模式,其中何处体现了依赖原则。

答:依赖倒置原则的基本思想是:①高层模块不应该依赖于低层模块,二者都应该依赖于抽象。②抽象不应该依赖于细节,细节应该依赖于抽象。Template method就体现了这个原则,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中,template method使得子类不改变一个算法的结构,即可重定义该算法的某些特定步骤。

10. 什么是单一职责原则?请举出一个使用了单一职责原则的软件设计模式,其中何处体现了单一职责原则。

答:基本思想:SRP使得一个类或一个模块承担的责任尽可能的少,使尽可能少的因素或动机影响该类或该模块,即增大类或模块的内聚性,减少其耦合度,SRP是所有原则中最简单的之一,也是最难正确运用的之一。