c面向对象的笔试题

c面向对象的笔试题

  C++由于过度的复杂性,以及与unix的文化相抵触,在unix/linux领域受到很多著名人士(比如Linux之父linus torvalds与著名黑客Eric S. Raymond)的强烈批评与抵制。下面就由第一范文网小编为大家介绍一下 c++面向对象的笔试题的文章,欢迎阅读。

  c++面向对象的笔试题篇1

  1. 重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?

  常考的题目。从定义上来说:

  重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

  重写:是指子类重新定义父类虚函数的方法。

  从实现原理上来说:

  重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译期间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!

  重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(因为只是把子类的指针赋值给父类指针,在编译期间没法根据父类指针知道具体是什么类型的子类,调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。

  2.类成员函数的重载、覆盖和隐藏区别

  答案:

  成员函数被重载的特征:

  (1)相同的范围(在同一个类中);

  (2)函数名字相同;

  (3)参数不同;

  (4)virtual关键字可有可无。

  覆盖是指派生类函数覆盖基类函数,特征是:

  (1)不同的范围(分别位于派生类与基类);

  (2)函数名字相同;

  (3)参数相同;

  (4)基类函数必须有virtual关键字。

  “隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

  (1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。

  (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

  c++面向对象的笔试题篇2

  1. 多态的作用?

  主要是两个:

  1.隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;

  2.接口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。

  2. Ado与的相同与不同?

  除了“能够让应用程序处理存储于DBMS 中的数据“这一基本相似点外,两者没有太多共同之处。但是Ado使用OLE DB 接口并基于微软的COM 技术,而 拥有自己的 接口并且基于微软的.NET 体系架构。众所周知.NET 体系不同于COM 体系, 接口也就完全不同于ADO和OLE DB 接口,这也就是说和ADO是两种数据访问方式。 提供对XML 的支持。

  3. New delete与malloc free的联系与区别?

  答案:都是在堆(heap)上进行动态的内存操作。用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的destructor,而free 不会调用对象的destructor.

  4. #defineDOUBLE(x) x+x,i = 5*DOUBLE(5); i 是多少?

  答案:i 为30。宏定义展开,5 * 5 + 5.

  5. 有哪几种情况只能用initialize list而不能用assignment?

  答案:当类中含有const、reference成员变量(因为这些只能在定义的时候赋值,后面不能修改);基类的构造函数都需要初始化表。

  6 C++是不是类型安全的?

  答案:不是。两个不同类型的指针之间可以强制转换(用reinterpret cast)。C#是类型安全的。

  7. main函数执行以前,还会执行什么代码?

  答案:全局对象的构造函数会在main 函数之前执行。

  8. 描述内存分配方式以及它们的区别?

  1) 从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。

  2) 在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。

  3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。

  9.struct 和 class的区别

  答案:struct 的成员默认是公有的,而类的成员默认是私有的。struct 和 class 在其他方面是功能相当的。

  从感情上讲,大多数的开发者感到类和结构有很大的差别。感觉上结构仅仅象一堆缺乏封装和功能的开放的内存位,而类就象活的并且可靠的社会成员,它有智能服务,有牢固的封装屏障和一个良好定义的接口。既然大多数人都这么认为,那么只有在你的类有很少的方法并且有公有数据(这种事情在良好设计的系统中是存在的!)时,你也许应该使用 struct 关键字,否则,你应该使用 class 关键字。

  10.当一个类A中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)

  答案:肯定不是零。举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。

  c++面向对象的笔试题篇3

  1. 在8086汇编下,逻辑地址和物理地址是怎样转换的?(Intel)

  答案:通用寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通用寄存器内地址,就得到了真正要访问的地址。

  2. 比较C++中的4种类型转换方式?

  请参考:,重点是static_cast, dynamic_cast和reinterpret_cast的区别和应用。

  一、C 风格(C-style)强制转型如下:

  (T) expression // cast expression to be of type T

  函数风格(Function-style)强制转型使用这样的语法:

  T(expression) // cast expression to be of type T

  这两种形式之间没有本质上的不同,它纯粹就是一个把括号放在哪的问题。我把这两种形式称为旧风格(old-style)的强制转型。

  二、 C++的四种强制转型形式:

  C++ 同时提供了四种新的强制转型形式(通常称为新风格的或 C++ 风格的强制转型):

  const_cast(expression)

  dynamic_cast(expression)

  reinterpret_cast(expression)

  static_cast(expression)

  每一种适用于特定的目的:

  dynamic_cast 主要用于执行“安全的向下转型(safe downcasting)”,也就是说,要确定一个对象是否是一个继承体系中的一个特定类型。它是唯一不能用旧风格语法执行的强制转型,也是唯一可能有重大运行时代价的强制转型。

  static_cast 可以被用于强制隐型转换(例如,non-const 对象转型为 const 对象,int 转型为 double,等等),它还可以用于很多这样的转换的反向转换(例如,void* 指针转型为有类型指针,基类指针转型为派生类指针),但是它不能将一个const 对象转型为 non-const 对象(只有const_cast 能做到),它最接近于C-style的转换。

  const_cast 一般用于强制消除对象的常量性。它是唯一能做到这一点的 C++ 风格的强制转型。

  reinterpret_cast 是特意用于底层的强制转型,导致实现依赖(implementation-dependent)(就是说,不可移植)的结果,例如,将一个指针转型为一个整数。这样的强制转型在底层代码以外应该极为罕见。

  旧风格的强制转型依然合法,但是新的形式更可取。首先,在代码中它们更容易识别(无论是人还是像 grep 这样的工具都是如此),这样就简化了在代码中寻找类型系统被破坏的地方的过程。第二,更精确地指定每一个强制转型的目的,使得编译器诊断使用错误成为可能。例如,如果你试图使用一个 const_cast 以外的新风格强制转型来消除常量性,你的代码将无法编译。

  ==

  == dynamic_cast .vs. static_cast

  ==

  classB { ... };

  class D : public B { ... };

  voidf(B* pb)

  {

  D* pd1 = dynamic_cast(pb);

  D* pd2 = static_cast(pb);

  }

  If pb really points to an object of type D, then pd1 and pd2 will get the same value.They will also get the same value if pb == 0.

  If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to return zero. However, static_cast relies on the programmer’s assertion that pb points to an object of type D and simply returns a pointer to that supposed D object.

  即dynamic_cast可用于继承体系中的向下转型,即将基类指针转换为派生类指针,比static_cast更严格更安全。dynamic_cast在执行效率上比static_cast要差一些,但static_cast在更宽上范围内可以完成映射,这种不加限制的映射伴随着不安全性.static_cast覆盖的变换类型除类层次的静态导航以外,还包括无映射变换,窄化变换(这种变换会导致对象切片,丢失信息),用VOID*的强制变换,隐式类型变换等...

  ==

  == static_cast .vs. reinterpret_cast

  ==

  reinterpret_cast是为了映射到一个完全不同类型的意思,这个关键词在我们需要把类型映射回原有类型时用到它.我们映射到的类型仅仅是为了故弄玄虚和其他目的,这是所有映射中最危险的.(这句话是C++编程思想中的原话)

  static_cast 和reinterpret_cast 操作符修改了操作数类型. 它们不是互逆的; static_cast 在编译时使用类型信息执行转换, 在转换执行必要的检测(诸如指针越界计算, 类型检查). 其操作数相对是安全的. 另一方面,reinterpret_cast 仅仅是重新解释了给出的对象的比特模型而没有进行二进制转换, 例子如下:

  int n=9; double d=static_cast < double > (n);

  上面的例子中, 我们将一个变量从 int 转换到 double. 这些类型的二进制表达式是不同的. 要将整数 9 转换到 双精度整数9, static_cast 需要正确地为双精度整数 d 补足比特位. 其结果为 9.0. 而reinterpret_cast的行为却不同:

  int n=9;

  double d=reinterpret_cast (n);

  这次, 结果有所不同. 在进行计算以后, d 包含无用值. 这是因为 reinterpret_cast 仅仅是复制 n 的比特位到 d, 没有进行必要的分析。