fw在c语⾔中的作⽤,【fw】c语⾔⾯试技巧2
16.
关联、聚合(Aggregation)以及组合(Composition)的区别?
涉及到UML中的⼀些概念:关联是表⽰两个类的⼀般性联系,⽐如“学⽣”和“⽼师”就是⼀种关联关系;聚合表⽰has-a的关系,是⼀种相对松散的关系,聚合类不需要对被聚合类负责,如下图所⽰,⽤空的菱形表⽰聚合关系:
从实现的⾓度讲,聚合可以表⽰为:
class A {...} class B { A* a;
.....}
⽽组合表⽰contains-a的关系,关联性强于聚合:组合类与被组合类有相同的⽣命周期,组合类要对被组合类负责,采⽤实⼼的菱形表⽰组合关系:
实现的形式是:
class A{...} class B{ A a; ...}
17.⾯向对象的三个基本特征,并简单叙述之?
1. 封装:将客观事物抽象成类,每个类对⾃⾝的数据和⽅法实⾏protection(private,
protected,public)
2.
继承:⼴义的继承有三种实现形式:实现继承(指使⽤基类的属性和⽅法⽽⽆需额外编码的能⼒)、可视继承(⼦窗体使⽤⽗窗体的外观和实现代码)、接⼝继承(仅使⽤属性和⽅法,实现滞后到⼦类实现)。前两种(类继承)和后⼀种(对象组合=>接⼝继承以及纯虚函数)构成了功能复⽤的两种⽅式。
3.
多态:是将⽗对象设置成为和⼀个或更多的他的⼦对象相等的技术,赋值之后,⽗对象就可以根据当前赋值给它的⼦对象的特性以不同的⽅式运作。简单的说,就是⼀句话:允许将⼦类类型的指针赋值给⽗类类型的指针。
18.
重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?
常考的题⽬。从定义上来说:
重载:是指允许存在多个同名函数,⽽这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
重写:是指⼦类重新定义复类虚函数的⽅法。
从实现原理上来说:
重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(⾄少对于编译器来说是这样的)。如,有两个同名函数:function
func(p:integer):integer;和function
func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调⽤,在编译器间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态⽆关!
重写:和多态真正相关。当⼦类重新定义了⽗类的虚函数后,⽗类指针根据赋给它的不同的⼦类指针,动态的调⽤属于⼦类的该函数,这样的函数调⽤在编译期间是⽆法确定的(调⽤的⼦类的虚函数的地址⽆法给出)。因此,这样的函数地址是在运⾏期绑定的(晚绑定)。
19.
多态的作⽤?
主要是两个:1.
隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重⽤;2.
接⼝重⽤:为了类在继承和派⽣的时候,保证使⽤家族中任⼀类的实例的某⼀属性时的正确调⽤。
20.
Ado与Ado的相同与不同?
除了“能够让应⽤程序处理存储于DBMS
中的数据“这⼀基本相似点外,两者没有太多共同之处。但是Ado使⽤OLE DB 接⼝并基于微软的COM
技术,⽽ADO.NET
拥有⾃⼰的ADO.NET 接⼝并且基于微软的.NET 体系架构。众所周知.NET 体系不同于COM 体系,ADO.NET
接⼝也就完全不同于ADO和OLE DB 接⼝,这也就是说ADO.NET 和ADO是两种数据访问⽅式。ADO 提供对XML
的⽀持。
21. New
delete 与malloc free
的联系与区别?答案:都是在堆(heap)上进⾏动态的内存操作。⽤malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会⾃动调⽤对象的构造函数。delete 会调⽤对象的destructor,⽽free
不会调⽤对象的destructor.
22. #define
DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?答案:i
为30。
23.
有哪⼏种情况只能⽤intialization list
⽽不能⽤assignment?
答案:当类中含有const、reference
成员变量;基类的构造函数都需要初始化表。
24. C++是不是类型安全的?
答案:不是。两个不同类型的指针之间可以强制转换(⽤reinterpret
cast)。C#是类型安全的。
25. main
函数执⾏以前,还会执⾏什么代码?答案:全局对象的构造函数会在main
函数之前执⾏。
26. 描述内存分配⽅式以及它们的区别?
1)
从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运⾏期间都存在。例如全局变量,static
变量。
2)
在栈上创建。在执⾏函数时,函数内局部变量的存储单元都可以在栈上创建,函数执⾏结束时这些存储单元⾃动被释放。栈内存分配运算内置于处理器的指令集。
3) 从堆上分配,亦称动态内存分配。程序在运⾏的时候⽤malloc
或new 申请任意多少的内存,程序员⾃⼰负责在何时⽤free 或delete
释放内存。动态内存的⽣存期由程序员决定,使⽤⾮常灵活,但问题也最多。
27.struct 和 class
的区别
答案:struct
的成员默认是公有的,⽽类的成员默认是私有的。struct 和 class 在其他⽅⾯是功能相当的。
从感情上讲,⼤多数的开发者感到类和结构有很⼤的差别。感觉上结构仅仅象⼀堆缺乏封装和功能的开放的内存位,⽽类就象活的并且可靠的社会成员,它有智能服务,有牢固的封装屏障和⼀个良好定义的接⼝。既然⼤多数⼈都这么认为,那么只有在你的类有很少的⽅法并且有公有数据(这种事情在良好设计的系统中是存在的!)时,你也许应该使⽤
struct 关键字,否则,你应该使⽤ class 关键字。
28.当⼀个类A
中没有⽣命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释⼀下编译器为什么没有让它为零。(Autodesk)答案:肯定不是零。举个反例,如果是零的话,声明⼀个class
A[10]对象数组,⽽每⼀个对象占⽤的空间是零,这时就没办法区分A[0],A[1]…了。
29. 在8086
汇编下,逻辑地址和物理地址是怎样转换的?(Intel)
答案:通⽤寄存器给出的地址,是段内偏移地址,相应段寄存器地址*10H+通⽤寄存器内地址,就得到了真正要访问的地址。
30. ⽐较C++中的4种类型转换⽅式?
,重点是static_cast,
dynamic_cast和reinterpret_cast的区别和应⽤。
31.分别写出BOOL,int,float,指针类型的变量a
与“零”的⽐较语句。
答案:
BOOL : if (
!a ) or if(a)
int
: if ( a == 0)
float : const
EXPRESSION EXP = 0.000001
if ( a < EXP && a
>-EXP)
pointer : if ( a != NULL) or if(a == NULL)
32.请说出const与#define
相⽐,有何优点?答案:1) const
常量有数据类型,⽽宏常量没有数据类型。编译器可以对前者进⾏类型安全检查。⽽对后者只进⾏字符替换,没有类型安全检查,并且在字符替换可能会产⽣意料不到的错误。
2) 有些集成化的调试⼯具可以对const
常量进⾏调试,但是不能对宏常量进⾏调试。
33.简述数组与指针的区别?
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。
(1)修改内容上的差别
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运⾏时错误
const的作用(2) ⽤运算符sizeof 可以计算出数组的容量(字节数)。sizeof(p),p
为指针得到的是⼀个指针变量的字节数,⽽不是p 所指的内存容量。C++/C
语⾔没有办法知道指针所指的内存容量,除⾮在申请内存时记住它。注意当数组作为函数的参数进⾏传递时,该数组⾃动退化为同类型的指针。char
a[] = "hello world";
char *p = a;
cout<< sizeof(a)
<< endl; // 12 字节
cout<< sizeof(p)
<< endl; // 4 字节
计算数组和指针的内存容量
void Func(char a[100])
{
cout<< sizeof(a)
<< endl; // 4 字节⽽不是100 字节
}
34.类成员函数的重载、覆盖和隐藏区别?答案:
a.成员函数被重载的特征:
(1)相同的范围(在同⼀个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可⽆。
b.覆盖是指派⽣类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派⽣类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
c.“隐藏”是指派⽣类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派⽣类的函数与基类的函数同名,但是参数不同。此时,不论有⽆virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派⽣类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual
关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
35. There are two int
variables: a and b, don’t use “if”, “? :”, “switch”or other
judgement statements, find out the biggest one of the two
numbers.
答案:( ( a + b ) + abs( a - b ) ) / 2
36.
如何打印出当前源⽂件的⽂件名以及源⽂件的当前⾏号?答案:
cout << __FILE__ ;
cout<<__line__>
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个⽂件中定义的,⽽是由编译器定义的。
37. main
主函数执⾏完毕后,是否可能会再执⾏⼀段代码,给出说明?答案:可以,可以⽤_onexit
注册⼀个函数,它会在main 之后执⾏int fn1(void), fn2(void), fn3(void), fn4
(void);
void main( void )
{
String str("zhanglin");
_onexit( fn1 );
_onexit( fn2 );
_onexit( fn3 );
_onexit( fn4 );
printf( "This is executed first.\n" );
}
int fn1()
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论