学习笔记问题大全【整理】1 C++

来源:互联网 发布:视频加文字软件 编辑:程序博客网 时间:2024/05/22 00:23

声明:以下大多问题都是网上找的,有部分答案根据自己个人的理解作出了修改,仅供参考

_______________

整理笔记:

关于C++语言概述 如基本符号、词汇、基本框架


问: 面向对象的程序设计思想是什么?
答:面向对象的程序设计思想简称OOP思想,是当今主流的程序设计范型,面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。万物皆对象的概念,由具有共同特征和行为的对象抽象的模型称之为“类”。
面向对象程序设计,是程序设计时把数据结构和对数据结构进行操作的方法封装形成一个个独立而又互相调用的对象的思想。
问:什么是类?
答:万物皆对象的概念,我们把一些具有共同特征和行为的对象抽象归类后形成一个集合的模型,称之为“类”。


问: 对象都具有的二方面特征是什么?分别是什么含义?
答:对象都具有的特征是:静态特征和动态特征。
  静态特征是指能描述对象的一些属性;动态特征是指对象表现出来的行为 。
问:C++有哪些性质(面向对象特点)
封装,继承和多态。
问:面向对象的三个基本特征(即同上题)是什么?并简单叙述之?
(1). 封装:将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)
(2) 继承:广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。
(3)多态:是将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。

问:为什么要封装,如何解释他的用意。
在面向对象程序设计语言中,封装是利用可重用成分构造软件系统的特性,它不仅支持系统的可重用性,而且还有利于提高系统的可扩充性;消息传递可以实现发送一个通用的消息而调用不同的方法;封装是实现信息隐蔽的一种技术,其目的是使类的定义和实现分离。
问:C++程序的基本框架

1结构程序设计框架

在C++的结构化程序设计框架中,函数是程序的基本组成单元,是程序中完成一定功能的模块。使用结构化程序设计方法编写出的C++程序包括一个主函数和若干个用户定义的函数。函数与函数之间是相对独立的并且是并行的,函数之间可以互相调用。同一个函数可以被一个或多个函数调用多次。主函数由系统调用,在主函数中调用其他函数。

(2)面向对象程序设计框架

面向对象的程序设计有三个主要的特征:封装、继承和多态。

封装:是对象和类概念的主要特征。封装是指把方法和数据装起来,对数据的访问只能通过已定义的接口。封装使得对象的内部实现与外部接口分离开来,对象的内部实现的改变并不影响使用这个对象的其他对象或应用。

继承:在面向对象的程序设计中,继承是指一个子类继承父类(或成为基类)的特征(数据结构和方法)。继承带来的好处是软件的复用,使用继承可以在已有软件的基础上构造新的软件,从而提高软件的生产率并保证软件的质量。

多态:在面向对象程序设计中主要是指变量多态和方法多态;变量多态是指同一个变量在运行时刻标识(表示)不同类型的对象,而方法多态主要是指同一方法做不一样的动作。多态使得消息发送者能给一组具有公共接口的对象发送相同的消息,接受者做出相应的动作。变量多态是方法多态的基础。

问:C和C++有什么不同?
从机制上:c是面向过程的(但c也可以编写面向对象的程序);c++是面向对象的,提供了类。但是,c++编写面向对象的程序比c容易
从适用的方向:c适合要求代码体积小的,效率高的场合,如嵌入式;c++适合更上层的,复杂的; llinux核心大部分是c写的,因为它是系统软件,效率要求极高。
从名称上也可以看出,c++比c多了+,说明c++是c的超集;那为什么不叫c+而叫c++呢,是因为c++比c来说扩充的东西太多了,所以就在c后面放上两个+;于是就成了c++
C语言是结构化编程语言,C++是面向对象编程语言。
C++侧重于对象而不是过程,侧重于类的设计而不是逻辑的设计。
问: #if!defined(AFX_…_HADE_H)
#define(AFX_…_HADE_H)
……
#endif作用?
防止该头文件被重复引用。
问:h头文件中的ifndef/define/endif 的作用?
答:防止该头文件被重复引用。
问:头文件的作用是什么?
答:(1)通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。
(2)头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。

问: 在头文件中进行类的声明,在对应的实现文件中进行类的定义有什么意义?
答:1这样可以提高编译效率,因为分开的话只需要编译一次生成对应的.obj文件后,再次应用该类的地方,这个类就不会被再次编译,从而大大提高了效率。
        2隐藏了代码

问:#include <filename.h> 和 #include “filename.h” 有什么区别?
答:对于#include <filename.h> ,编译器从标准库(Standard Library)路径开始搜索 filename.h
对于#include “filename.h” ,编译器从用户的工作路径开始搜索 filename.h
问:#i nclude<file.h> 与 #i nclude "file.h"的区别?(同上一题)
答:前者是从Standard Library的路径寻找和引用file.h,而后者是从当前工作路径搜寻并引用file.h。
问:#define DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?
答案:i 为30。  
问:C++是不是类型安全的?
答案:不是。两个不同类型的指针之间可以强制转换(用reinterpret cast) .C#是类型安全的。
问:如何判断一段程序是由C 编译程序还是由C++编译程序编译的?
答案:
#ifdef __cplusplus
  cout<<"c++";
#else
  cout<<"c";
#endif
注意,后面很多代码啊。代码不看也罢。

问:main 函数执行以前,还会执行什么代码?
答案:全局对象的构造函数会在main 函数之前执行,为malloc分配必要的资源,等等

问:C++里面是不是所有的动作都是main()引起的?如果不是,请举例。

答:当然不是的.并不是所有的动作都是由main()引起的,只是编译器是由main()开始执行的
静态变量和全局变量的初始化和内存分配早在main之前完成
内联,模板,宏的扩展等更是编译期行为,也不是main()完成的
注:C++和main()逻辑上没有必然的联系。

问:main 主函数执行完毕后,是否可能会再执行一段代码,给出说明?
答案:可以,可以用_onexit 注册一个函数,它会在main 之后执行intfn1(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()
{
  printf( "next.\n" );
return0;
}
int fn2()
{
  printf( "executed " );
return0;
}
int fn3()
{
  printf( "is " );
return0;
}
int fn4()
{
  printf( "This " );
return0;
}
The _onexit function is passedthe address of a function (func) to be called whenthe program terminatesnormally. Successive calls to _onexit create a registerof functions that areexecuted in LIFO (last-in-first-out) order. The functionspassed to _onexitcannot take parameters.

_______________

_______________

整理笔记:

关于C++数据类型 表达式 基本运算

问: 简述枚举类型?
枚举方便一次定义一组常量,使用起来很方便;

问:C++中的0和1,假和真?
 c/c++ 里面一般是 0 为 false, 非 0 为真。
布尔型的取值为true或者false。布尔型变量的应用,例如bool   flag;则布尔型数据的变量flag取值:只有 false 和 true 两个值,即分别是0和1。
问:比较C++中的4种类型转换方式?
重点是static_cast, dynamic_cast和reinterpret_cast的区别和应用。
dynamic_casts在帮助你浏览继承层次上是有限制的。它不能被用于缺乏虚函数的类型上,它被用于安全地沿着类的继承关系向下进行类型转换。如你想在没有继承关系的类型中进行转换,你可能想到static_cast

问:在Win32下 char, int, float, double各占多少位?
(1)        Char         占用8位
(2)        Int 占用32位
(3)        Float 占用32位
(4)        Double 占用64位

问:unsigned short A = 10;
printf("~A = %u/n", ~A);


char c=128;
printf("c=%d/n",c);
这两题分别输出多少?并分析过程
第一题,

A=10,为无符号型,转换为二进制为0000 0000 0000 0000 0000 0000 0000 1010
所以~A的二进制位1111 1111 1111 1111 1111 1111 1111 0101即0xFFFFFFF5,~A =0xfffffff5。

0xFFFFFFF5,如果转换为符号整型的话则为-11,因为输出的是无符号整型,无符号整型的范围为0~4294967295,而0xFFFFFFF5转换为无符号十进制整型为4294967285

int值 为-11,但输出的是uint。所以输出4294967285

第二题,c=0x10,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。
这两道题都是在考察二进制向int或uint转换时的最高位处理。

问:关于位操作(Bit manipulation)

下面的代码输出是什么,为什么?
 void foo(void)

{
unsigned int a = 6;
int b = -20;
(a+b > 6)? puts("> 6") : puts("<= 6");
}
这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是“>6”。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。

问:不能做switch()的参数类型是:
答 、switch的参数不能为实型。


问:请说出static和const关键字尽可能多的作用
解答:static关键字至少有下列n个作用:
  (1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
  (2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
  (3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
  (4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
  (5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
  总结const的应用和作用?至少有下列n个作用定义常量、常指针、指向常变量的指针、修饰函数参数(函数的常参数)、类的常成员函数、const对象、修饰函数返回值
  (1)常量:欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
  (2)常量指针和指向常量的指针:对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
  (3)函数的常参数:在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
  (4)类的常成员函数:对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
  (5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:
const classA operator*(const classA& a1,const classA& a2);
  operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错:
classA a, b, c;
(a * b) = c; // 对a*b的结果赋值
  操作(a * b) = c显然不符合编程者的初衷,也没有任何意义。
剖析:
  惊讶吗?小小的static和const居然有这么多功能,我们能回答几个?如果只能回答1~2个,那还真得闭关再好好修炼修炼。
  这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入,没有一定的知识广度和深度,不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。

问:慧通公司,关于const的问题:

char * const p;
char const * p
const char *p
上述三个有什么区别?
char * const p; //常量指针,p的值不可以修改
char const * p;//指向常量的指针,指向的常量值不可以改
const char *p; //和char const *p是是一个意思。都是p所指向的变量的值不能改变

问:char *const p 与 char const * p const char * p的区别,并举例说明。(跟上一个是同一问题)
const char * p 和 char const * p 是一个意思,都是p所指向的变量的值不能改变,
例如:
const char ch = 'a';
const char* p = &ch;
*p = 'b';   //这样是错的

char* const p,意思是p所指向的地址是不能改变的,例如:
char* const p = &ch1;
p = &ch2;  //这样是错的

问:const char *p,char *  const p;的区别。(跟上一个是同一问题)
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。

问:以下代码输出结果是什么?
char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";
cout << ( str1 == str2 ) << endl;
cout << ( str3 == str4 ) << endl;
cout << ( str5 == str6 ) << endl;
cout << ( str7 == str8 ) << endl;
结果是:0 0 1 1
解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;
而str5,str6,str7,str8是指针,它们指向相同的常量区域。

问:请说出const与#define 相比,有何优点?
答案:
Const作用:定义常量、修饰函数参数、修饰函数返回值、常指针、指向常变量的指针。被Const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。
问:关键字const有什么含意?
表示不可以修改的变量。
我只要一听到被面试者说:"const意味着常数",我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着"只读"就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)
如果应试者能正确回答这个问题,我将问他一个附加的问题:
下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
/******/
前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:
1) 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
2) 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3) 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

问:关键字const是什么含意?
我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字 const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由:
1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
2). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。
3). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

问:在函数后面加个const是怎么理解的?
在函数后面加个const一般在类的成员函数中使用,表示这个函数不修改数据成员的值。
另:void set_prt_val(int val)const {*ptr= val}理解:指针ptr指向的内容不是类的数据成员,所以这可这么写:*ptr = val;但这个指针在这个函数中不能修改。如果写成这样:ptr = &i(假设i是另外一个整形变量)就不对了,因为改变了指针的内容。

问:const #define 区别
const定义常量是有数据类型的,这样const定义的常量编译器可以对其进行数据静态类型安全检查,而#define宏定义的常量却只是进行简单的字符替换,没有类型安全检查,且有时还会产生边际效应

问: 说明#define和const在语法和含义上有什么不同?(跟上一题相同)
(1)        #define是C语法中定义符号变量的方法,符号常量只是用来表达一个值,在编译阶段符号就被值替换了,它没有类型;
(2)        Const是C++语法中定义常变量的方法,常变量具有变量特性,它具有类型,内存中存在以它命名的存储单元,可以用sizeof测出长度。

问:说出字符常量和字符串常量的区别,并使用运算符sizeof计算有什么不用?
字符常量是指单个字符,字符串常量以‘\0’结束,使用运算符sizeof计算多占一字节的存储空间。

问:在什么时候使用常引用?
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。
问:什么是常指针,什么是指向常变量的指针?
常指针
的含义是该指针所指向的地址不能变,但该地址所指向的内容可以变化,使用常指针可以保证我们的指针不能指向其它的变量,
指向常变量的指针是指该指针的变量本身的地址可以变化,可以指向其它的变量,但是它所指的内容不可以被修改。指向长变量的指针定义,

问:移位和乘以2的区别
不管你采用哪种方式,任何合格的优化编译程序都会产生相同的代码,因此你可以采用使程序的上下文更易读的那种方式。你可以用DOS/Windows上的CODEVIEW或UNIX机上的反汇编程序(通常被称为"dis”)这样的工具来查看下述程序的汇编代码: 例10.4乘以2和左移一位经常是相同的    void main()    {      unsigned int test_nbr = 300;      test_nbr * =2;      test_nbr = 300;      test_nbr << = 1;    }

问:#define DOUBLE(x) x+x ,i = 5*DOUBLE(5); i 是多少?
答案:i 为30。(注意直接展开就是了) 5 * 5 + 5

问: int i=10, j=10, k=3; k*=i+j; k最后的值是?
答:60,此题考察优先级,实际写成: k*=(i+j);,赋值运算符优先级最低

问:定义 int **a[3][4], 则变量占有的内存空间为:_____

问:C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?
int a = 5, b = 7, c;
c = a+++b;
这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成:
c = a++ + b;
因此, 这段代码持行后a = 6, b = 7, c = 12。
如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题.
问:关于数据声明(Data declarations),用变量a给出下面的定义
a) 一个整型数(An integer)
b) 一个指向整型数的指针(A pointer to an integer)
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)
d) 一个有10个整型数的数组(An array of 10 integers)
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢? 
问:下列哪两个是等同的
  int b;
  A const int* a = &b;
  B const* int a = &b;
  C const int* const a = &b;
  D int const* const a = &b;

问: 在定义一个宏的时候要注意什么?
        定义部分的每个形参和整个表达式都必须用括号括起来,以避免不可预料的错误发生

问: 对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
答:c用宏定义,c++用inline

问:用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
 #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在这想看到几件事情:
1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
2). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。
3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。
4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
问:交换两个数的宏定义
 交换两个参数值的宏定义为:. #define SWAP(a,b) (a)=(a)+(b);(b)=(a)-(b);(a)=(a)-(b);

问:写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) (A) : (B))
这个测试是为下面的目的而设的:
1). 标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,
对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
2). 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
3). 懂得在宏中小心地把参数用括号括起来
4). 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?

问:写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。另外,当你写下面的代码时会发生什么事?
least = MIN(*p++, b);
解答:
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
MIN(*p++, b)会产生宏的副作用
剖析:
  这个面试题主要考查面试者对宏定义的使用,宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对“参数”进行的是一对一的替换。
程序员对宏定义的使用要非常小心,特别要注意两个问题:
(1)谨慎地将宏定义中的“参数”和整个宏用用括弧括起来。所以,严格地讲,下述解答:
#define MIN(A,B) (A) <= (B) ?(A) : (B)
#define MIN(A,B) (A <= B ? A : B )都应判0分;
(2)防止宏的副作用。
宏定义#define MIN(A,B) ((A) <= (B) ?(A) : (B))对MIN(*p++, b)的作用结果是:
((*p++) <= (b) ? (*p++) :(*p++))
这个表达式会产生副作用,指针p会作三次++自增操作。
除此之外,另一个应该判0分的解答是:
#define MIN(A,B) ((A) <= (B) ?(A) : (B));
  这个解答在宏定义的后面加“;”,显示编写者对宏的概念模糊不清,只能被无情地判0分并被面试官淘汰。

问:写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。
        #define MIN(A,B) ((A) <= (B) ? (A) : (B))
这个测试是为下面的目的而设的:
1) 标识#define在宏中应用的基本知识。这是很重要的。因为在  嵌入(inline)操作符 变为标准C的一部分之前,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
2)三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
3) 懂得在宏中小心地把参数用括号括起来
4) 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事?
        least = MIN(*p++, b);

问:(华为c/c++面试题及答案 )写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值(3分)
int a = 4;
(A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);
a = ?
答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a) += a;
改后答案依次为9,10,10,11

问:某32位系统下, C++程序,请计算sizeof 的值(5分).
char str[] = “http://www.ibegroup.com/”
char *p = str ;
int n = 10;
请计算
sizeof (str ) = ?(1)
sizeof ( p ) = ?(2)
sizeof ( n ) = ?(3)
void Foo ( char str[100]){
请计算
sizeof( str ) = ?(4)
}
void *p = malloc( 100 );
请计算
sizeof ( p ) = ?(5)
答:(1)17 (2)4 (3) 4 (4)4 (5)4
问: 评价下面的代码片断:
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */
对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:
unsigned int compzero = ~0;
这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。
到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧...

问:请写出下列代码的输出内容
#i nclude
main()
{
int a,b,c,d;
a=10;
b=a++;
c=++a;
d=10*a++;
printf("b,c,d:%d,%d,%d",b,c,d);
return 0;
}
答10,12,120

_______________

_______________

整理笔记:

关于C++基本语句

问:以下代码有什么问题?
cout << (true?1:"1") << endl;
答:三元表达式“?:”问号后面的两个操作数必须为同一类型。

问:写出float x 与“零值”比较的if语句。
      if(x>0.000001&&x<-0.000001)

问:分别写出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)
问:语句for( ;1 ;)有什么问题?它是什么意思?
答:无限循环,和while(1)相同。
问:do……while和while……do有什么区别?
答 、前一个循环一遍再判断,后一个判断以后再循环
问:死循环(Infinite loops)。嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?
这个问题用几个解决方案。我首选的方案是:
while(1)
{
}
一些程序员更喜欢如下方案:
for(;;)
{
}
这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的
基本原理。如果他们的基本答案是:“我被教着这样做,但从没有想到过为什么。”这会给我留下一个坏印象。
第三个方案是用 goto
Loop:
...
goto Loop;
应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。

_______________

_______________

整理笔记:

关于C++数组 指针 引用

问:什么是指针?谈谈你对指针的理解?
指针是一个变量,该变量专门存放内存地址;
指针变量的类型取决于其指向的数据类型,在所指数据类型前加*
指针变量的特点是它可以访问所指向的内存。
问:指针的几种典型应用情况?
int *p[n];-----指针数组,每个元素均为指向整型数据的指针。
int (*)p[n];------p为指向一维数组的指针,这个一维数组有n个整型数据。
int *p();----------函数带回指针,指针指向返回的值。
int (*)p();------p为指向函数的指针。
问:什么是“引用”?申明和使用“引用”要注意哪些问题?
答:引用就是某个目标变量的“别名”(alias),对应用的操作与对变量直接操作效果完全相同。申明一个引用的时候,切记要对其进行初始化。引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。不能建立数组的引用。
问:将“引用”作为函数参数有哪些特点?
(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。
(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。
(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

问:什么时候需要“引用”?
流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。以上参考:http://develop.csai.cn/c/NO0000021.htm
问:C++中指针与引用的区别:

参考答案1:
相同点:指针和引用都是地址的概念,指针指向一块内存,他的值是这块内存的地址;而引用是一块内存的别名。
区别:
(1)指针是一个实体,而引用只是一个别名,是指向的一块内存的别名;
(2)引用只能被定义一次,“从一而终”,指针可以多次赋值
(3)引用没有const,指针有const(常量);(int const &a没有意义,但是 const int &a是有意义的;int const &a指的是引用的值不可以改变,引用的值本身是不可以改变的,所以这样修饰是无意义的)
(4)引用不能为空,指针可以为空;指针需要做非空检查
(5)对sizeof()操作符,引用的结果是引用所指向的变量的类型大小,而指针是指的指针类型的大小
(6)对于++的意义不一样
参考:http://blog.sina.com.cn/s/blog_673ef8130100imsp.html
参考答案2:
  1) 引用必须被初始化,指针不必。
 2) 引用初始化以后不能被改变,指针可以改变所指的对象。
 3) 不存在指向空值的引用,但是存在指向空值的指针。
参考答案3:
指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;
而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
此外,就是上面提到的对函数传ref和pointer的区别。

问:简述数组与指针的区别?
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。
(1)修改内容上的差别
char a[] = “hello”;
a[0] = ‘X’;
char *p = “world”; // 注意p 指向常量字符串
p[0] = ‘X’; // 编译器不能发现该错误,运行时错误
(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 字节
}
问:在另外的一些操作符中,却千万不能返回引用:+-*/ 四则运算符。它们不能返回引用,Effective C++[1]的Item23详细的讨论了这个问题。主要原因是这四个操作符没有side effect,因此,它们必须构造一个对象作为返回值,可选的方案包括:返回一个对象、返回一个局部变量的引用,返回一个new分配的对象的引用、返回一个静态对象引用。根据前面提到的引用作为返回值的三个规则,第2、3两个方案都被否决了。静态对象的引用又因为((a+b) == (c+d))会永远为true而导致错误。所以可选的只剩下返回一个对象了。
问:“引用”与多态的关系?
引用是除指针外另一个可以产生多态效果的手段。这意味着,一个基类的引用可以指向它的派生类实例。例
Class A; Class B : Class A{...};  B b; A& ref = b;

问:在什么时候需要使用“常引用”? 
如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。
问:常引用声明方式:const 类型标识符 &引用名=目标变量名;
例1
int a ;
const int &ra=a;
ra=1; //错误
a=1; //正确
例2
string foo( );
void bar(string & s);
//那么下面的表达式将是非法的:
bar(foo( ));
bar("hello world");
原因在于foo( )和"hello world"串都会产生一个临时对象,而在C++中,这些临时对象都是const类型的。因此上面的表达式就是试图将一个const类型的对象转换为非const类型,这是非法的。引用型参数应该在能被定义为const的情况下,尽量定义为const 。
问:将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?
格式:类型标识符 &函数名(形参列表及类型说明){ //函数体 }
好处:在内存中不产生被返回值的副本;(注意:正是因为这点原因,所以返回一个局部变量的引用是不可取的。因为随着该局部变量生存期的结束,相应的引用也会失效,产生runtime error! 注意事项:
(1)不能返回局部变量的引用。这条可以参照Effective C++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
(2)不能返回函数内部new分配的内存的引用。这条可以参照Effective C++[1]的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。
(3)可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
(4)流操作符重载返回值申明为“引用”的作用:
流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << "hello" << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。可选的其它方案包括:返回一个流对象和返回一个流对象指针。但是对于返回一个流对象,程序必须重新(拷贝)构造一个新的流对象,也就是说,连续的两个<<操作符实际上是针对不同对象的!这无法让人接受。对于返回一个流指针则不能连续使用<<操作符。因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续赋值。因此引用成了这个操作符的惟一返回值选择。

#i nclude <iostream.h>
int &put(int n);
int vals[10];
int error=-1;
void main()
{
put(0)=10; //以put(0)函数值作为左值,等价于vals[0]=10;
put(9)=20; //以put(9)函数值作为左值,等价于vals[9]=20;
cout<<vals[0];
cout<<vals[9];
}
int &put(int n)
{
if (n>=0 && n<=9 ) return vals[n];
else { cout<<"subscript error"; return error; }
}
问:Itearator各指针的区别
 游标和指针
我说过游标是指针,但不仅仅是指针。游标和指针很像,功能很像指针,但是实际上,游标是通过重载一元的”*”和”->”来从容器中间接地返回一个值。将这些值存储在容器中并不是一个好主意,因为每当一个新值添加到容器中或者有一个值从容器中删除,这些值就会失效。在某种程度上,游标可以看作是句柄(handle)。通常情况下游标(iterator)的类型可以有所变化,这样容器也会有几种不同方式的转变:
iterator——对于除了vector以外的其他任何容器,你可以通过这种游标在一次操作中在容器中朝向前的方向走一步。这意味着对于这种游标你只能使用“++”操作符。而不能使用“--”或“+=”操作符。而对于vector这一种容器,你可以使用“+=”、“—”、“++”、“-=”中的任何一种操作符和“<”、“<=”、“>”、“>=”、“==”、“!=”等比较运算符。
 _______________

_______________

整理笔记:

关于C++函数 定义 调用 传参 返回值 变量作用域 递归函数 函数重载 内联函数 带缺省参数值的函数等

问: C++函数中值的传递方式
有三种方式:值传递、指针传递、引用传递
问:数组在做函数实参的时候会转变为什么类型?
指针类型。
问:论述含参数的宏与函数的优缺点。

1.函数调用时,先求出实参表达式的值,然后带入形参。而使用带参的宏只是进行简单的字符替换。

2.函数调用是在程序运行时处理的,分配临时的内存单元;而宏展开则是在编译时进行的,在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。3.对函数中的实参和形参都要定义类型,二者的类型要求一致,如不一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时带入指定的字符即可。宏定义时,字符串可以是任何类型的数据。4.调用函数只可得到一个返回值,而用宏可以设法得到几个结果。5.使用宏次数多时,宏展开后源程序长,因为每展开一次都使程序增长,而函数调用不使源程序变长。6.宏替换不占运行时间。而函数调用则占运行时间(分配单元、保留现场、值传递、返回)。一般来说,用宏来代表简短的表达式比较合适。


问: 函数指针和指针函数的区别?
函数指针是指指向一个函数入口的指针;
指针函数是指函数的返回值是一个指针类型。
问:请问函数的声明,定义,和实现有什么区别?
其实真正意义上应该没有实现这个词。
我想仅仅提供原形的叫声明,这个时候具体的定义部分可以说是实现了
但是如果你在声明的时候连所有的工作都做了,应该是定义,这里一般不讲“实现”
问:return 0是什么意思?
"return 0"出现可能有两种能,一是在主函数〔main()函数〕中出现,二是在自定义函数中出现,在主函数中出现是代表的是无系统返回值,即执行到这时直接跳出程序了。在自定义函数中出现时代表的是无函数返回值,只执行了代码,做了一些代码让做的事,但不返回数值给主调函数。
问:全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
答 、全局变量储存在静态数据区,局部变量在栈中。
问: 解释局部变量、全局变量和静态变量的含义。

(1)局部变量
      在一个函数内部定义的变量是内部变量,它只在本函数范围内有效
,也就是说只有在本函数内才能使用它们,在此函数以外时不能使用这些变量的,它们称为局部变量.
   1.主函数main中定义的变量也只在主函数中有效,而不因为在主函数中定义而在整个文件或程序中有效.
   2.不同函数中可以使用名字相同的变量,它们代表不同的对象,互不干扰.
   3.形式参数也使局部变量.
   4.在一个函数内部,可以在复合语句中定义变量,这些变量只在本符合语句中有效.
(2)全局变量
       在函数外定义的变量是外部变量,外部变量是全局变量,全局变量可以为本文件中其它函数所共用,它的有效范围从定义变量的位置开始到本源文件结束
.
   1.设全局变量的作用:增加了函数间数据联系的渠道.
   2.建议不再必要的时候不要使用全局变量,因为
        a.全局变量在程序的全部执行过程中都占用存储单元.
        b.它使函数的通用性降低了c.使用全局变量过多,会降低程序的清晰性.
   3.如果外部变量在文件开头定义,则在整个文件范围内都可以使用该外部变量,如果不再文件开头定义,按上面规定作用范围只限于定义点到文件终了.如果在定义点之前的函数想引用该外部变量,则应该在该函数中用关键字extern作外部变量说明.
   4.如果在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内,外部变量不起作用.
(3)静态变量 
      静态变量:在程序运行期间分配固定的存储空间的变量,叫做静态变量。静态变量的作用范围要看静态变量的位置,如果在函数里,则作用范围就是这个函数.
       静态全局变量,只在本文件可以用,虽然整个程序包含多个文件,但静态全局变量只能用在定义它的那个文件里,却不能用在程序中的其他文件里.
它是定义存储因型为静态型的外部变量,其作用域是从定义点到程序结束,所不同的是存储类型决定了存储地点,静态型变量是存放在内存的数据区中的,它们在程序开始运行前就分配了固定的字节,在程序运行过程中被分配的字节大小是不改变的,只有程序运行结束后,才释放所占用的内存.

  【attention】
   操作系统和编译器如何判断全局变量和局部变量?
   操作系统和编译器是根据程序运行的内存区域来获取该变量的类型.程序的全局数据放在所分配内存的全局数据区,程序的局部数据放在栈区.  
  【attention】
   <1>static全局变量与普通的全局变量有什么区别?
          全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式.这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的.而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它.由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误.从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围.
   <2>static函数与普通函数有什么区别?
          static函数与普通函数作用域不同.仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义.对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件.
   <3>static局部变量和普通局部变量有什么区别?
          static局部变量只被初始化一次,下一次依据上一次结果值;

参考资料:http://blog.csdn.net/shuaishuai80/article/details/6150278
问:  程序的局部变量存在于(栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中。

问: 简述全局变量的优缺点?
全局变量也称为外部变量,它是在函数外部定义的变量,它属于一个源程序文件,它保存上一次被修改后的值,便于数据共享,但不方便管理,易引起意想不到的错误。

问: 局部变量能否和全局变量重名(即使用同名)?
答、能,局部会屏蔽全局。要用全局变量,需要使用"::"(域运算符)。

局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内
 问: 如何引用一个已经定义过的全局变量?
答 、可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变量,假定你将那个变量写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错
问: 全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的 ?
 全局变量的生命周期是整个程序运行的时间,而局部变量的生命周期则是局部函数或过程调用的时间段。其实现是由编译器在编译时采用不同内存分配方法。全局变量在main函数调用后,就开始分配,如果是静态变量则是在main函数前就已经初始化了。而局部变量则是在用户栈中动态分配的(还是建议看编译原理中的活动记录这一块)
问: 全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
答 、可以,在不同的C文件中以static形式来声明同名全局变量。
可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错
问:C++中求绝对值函数abs()和fabs()一样吗?
abs是用于求整数的绝对值,fabs是用于求浮点数的绝对值的。
头文件是#include <cmath>
C语言数学函数:fabs
原型:在TC中原型是extern float fabs(float x);,在VC6.0中原型是double fabs( double x );。
用法:#include <math.h>
问:fabs(x0-x1)>=0.000001的另一个表达方式。
和fabs(x0-x1)>=1e-6
问:类成员函数的重载、覆盖和隐藏区别?
答案:a.成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
b.覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual 关键字。
 c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
问:重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?
这个是常考的题目。
从定义上来说:
重载:是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
重写:是指子类重新定义父类虚函数的方法。
从实现原理上来说:
重载:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!
重写:和多态真正相关。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚绑定)。
问:有关重载函数
 返回值类型不同构不成重载
参数参数顺序不同能构成重载
c++函数同名不同返回值不算重载!函数重载是忽略返回值类型的。
---------------------------------------------
问:成员函数被重载的特征有:
1) 相同的范围(在同一个类中);
2) 函数名字相同;
3) 参数不同;
4) virtual关键字可有可无。
5) 成员函数中 有无const (函数后面) 也可判断是否重载

 

 _______________

_______________

整理笔记:

关于C++类与对象 对象指针 构造函数 析构函数 静态数据成员 静态成员函数 常数据成员 常成员函数 友元函数和友元类 对象数组和成员对象

问:类的声明和实现的分开的好处?
1. 起保护作用;
2. 提高编译的效率。
问: 请说出类中private,protect,public三种访问限制类型的区别
private是私有类型,只有本类中的成员函数访问;protect是保护型的,本类和继承类可以访问;public是公有类型,任何类都可以访问.
问: 类中成员变量怎么进行初始化?
可以通过构造函数的初始化列表或构造函数的函数体实现。
问: 关于对象成员进行初始化的次序是什么?
答:它的次序完全不受它们在初始化表中次序的影响,只与成员对象在类中声明的次序来决定的。
问:  类和对象之间的关系是什么?
答:类是对象的抽象,对象是类的实例。
问:  对类的成员的访问属性有什么?
答:public,protected,private。

问:C++中的空类,默认产生哪些类成员函数?分别有什么作用
答:默认构造函数  
析构函数  
拷贝构造函数  
赋值运算符(operator=)  
取址运算符(operator&)(一对,一个非const的,一个const的)
class Empty

{

  public:

  Empty(); // 缺省构造函数

  Empty( const Empty& ); // 拷贝构造函数

  ~Empty(); // 析构函数

  Empty& operator=( const Empty& ); // 赋值运算符

  Empty* operator&(); // 取址运算符

  const Empty* operator&() const; // 取址运算符 const

};

当然,所有这些只有当被需要才会产生。比如你定义了一个类,但从来定义过该类的对象,也没使用过该类型的函数参数,那么基本啥也不会产生。在比如你从来没有进行过该类型对象之间的赋值,那么operator=不会被产生。

问: C++编译器自动为类产生的四个缺省函数是什么?
答:默认构造函数,拷贝构造函数,析构函数,赋值函数。
问:一个类的构造函数和析构函数什么时候被调用,是否需要手工调用?
答:构造函数在创建类对象的时候被自动调用,析构函数在类对象生命期结束时,由系统自动调用。
问: 构造函数和析构函数的调用顺序? 析构函数为什么要虚拟?
答案:构造函数的调用顺序:基类构造函数—对象成员构造函数—派生类构造函数;析构函数的调用顺序与构造函数相反。析构函数虚拟是为了防止析构不彻底,造成内存的泄漏。
问:C++中class 和 struct 的区别?
参考答案1:
struct 的成员默认是公有的,而类的成员默认是私有的。
参考答案2:从语法上,在C++中(只讨论C++中)。class和struct做类型定义时只有两点区别:
(一)默认继承权限。如果不明确指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理;
(二)成员的默认访问权限。class的成员默认是private权限,struct默认是public权限。
除了这两点,class和struct基本就是一个东西。语法上没有任何其它区别。
参考答案3:
问:C++中struct 和 class 的区别
答案:struct 的成员默认是公有的,而类的成员默认是私有的。struct 和 class 在其他方面是功能相当的。从感情上讲,大多数的开发者感到类和结构有很大的差别。感觉上结构仅仅象一堆缺乏封装和功能的开放的内存位,而类就象活的并且可靠的社会成员,它有智能服务,有牢固的封装屏障和一个良好定义的接口。既然大多数人都这么认为,那么只有在你的类有很少的方法并且有公有数据(这种事情在良好设计的系统中是存在的!)时,你也许应该使用 struct 关键字,否则,你应该使用 class 关键字。
问:C++中类型为private的成员变量可以由哪些函数访问?
只可以由本类中的成员函数和友员函数访问
问:什么叫智能指针?
当一个类中,存在一个指向另一个类对象的指针时,对指针运算符进行重载,那么当前类对象可以通过指针像调用自身成员一样调用另一个类的成员。
问: struct(结构) 和 union(联合)的区别?
(1). 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员(所有成员共用一块地址空间), 而结构的所有成员都存在(不同成员的存放地址不同)。
 (2). 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不同成员赋值是互不影响的。
问:编译报错error C2524: 'B' : destructors must have a 'void' formal parameter list,这是什么意思?
析构函数形参必须是空。
问: 在类的内部定义成员函数的函数体,这种函数会具备那种属性?
答:这种函数会自动为内联函数,这种函数在函数调用的地方在编译阶段都会进行代码替换。
问: 成员函数通过什么来区分不同对象的成员数据?为什么它能够区分?
答:通过this指针来区分的, 因为它指向的是对象的首地址。
问: 构造函数与普通函数相比在形式上有什么不同?(构造函数的作用,它的声明形式来分析)
答:构造函数是类的一种特殊成员函数,一般情况下,它是专门用来初始化对象成员变量的。
构造函数的名字必须与类名相同,它不具有任何类型,不返回任何值。
问:  拷贝构造函数在哪几种情况下会被调用?
答:1.当类的一个对象去初始化该类的另一个对象时;
2.如果函数的形参是类的对象,调用函数进行形参和实参结合时;
3.如果函数的返回值是类对象,函数调用完成返回时。
问:   赋值运算符和拷贝构造函数的区别与联系?
答:相同点:都是将一个对象copy到另一个中去。
不同点:拷贝构造函数涉及到要新建立一个对象。
问:  什么时候必须重写拷贝构造函数?
答:当构造函数涉及到动态存储分配空间时,要自己写拷贝构造函数,并且要深拷贝。
问: 构造函数的调用顺序是什么?
答:1.先调用基类构造函数
    2.按声明顺序初始化数据成员
  3.最后调用自己的构造函数。
问:   在哪种情况下要调用该类的析构函数?
答:对象生命周期结束时。
问:什么时候需要用虚析构函数?
当基类指针指向用new运算符生成的派生类对象时,delete基类指针时,派生类部分没有释放掉而造成释放不彻底现象,需要虚析构函数。
问:子类析构时要调用父类的析构函数吗?
参考答案1:析构函数调用的次序是先派生类的析构后基类的析构,也就是说在基类的的析构调用的时候,派生类的信息已经全部销毁了(JAVA无析构函数深拷贝和浅拷贝)
参考答案2:程序结束之后当然所有的对象都会销毁,所以这个先析构派生类再析构基类是基于确定基类对象需要被销毁的时候进行的,但是当程序未结束,而一个派生类出了它的作用域的时候,这个时候仅仅调用子类的析构函数,而基类并不会被析构。
问: 哪几种情况必须用到初始化成员列表?
答:类的成员是常量成员初始化;
类的成员是对象成员初始化,而该对象没有无参构造函数。
类的成员常变量时。
问:  什么是常对象?
答:常对象是指在任何场合都不能对其成员的值进行修改的对象。
问:static有什么用途?(请至少说明两种)
答 、1.限制变量的作用域(文件级的)。
 2.设置变量的存储域(全局数据区)。
问: 关键字static的作用是什么?
这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
1). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
2). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
3). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数
据和代码范围的好处和重要性。
问:总结static的应用和作用?
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
问: static函数与普通函数有什么区别?
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
问: 静态函数存在的意义?
答:1静态私有成员在类外不能被访问,可通过类的静态成员函数来访问;
  2当类的构造函数是私有的时,不像普通类那样实例化自己,只能通过静态成员函数来调用构造函数。
问:Static 作用是什么
首先static的最主要功能是隐藏,其次因为static变量存放在静态存储区,所以它具备持久性和默认值0。

问:static 全局变量、局部变量、函数与普通全局变量、局部变量、函数
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
答 、全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。
从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。
static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件
static全局变量与普通的全局变量有什么区别:static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
程序的局部变量存在于(堆栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中。
问:在类外有什么办法可以访问类的非公有成员?
答:友元,继承,公有成员函数。
问:什么叫抽象类?
答:不用来定义对象而只作为一种基本类型用作继承的类。
问:对象间是怎样实现数据的共享的?
答:通过类的静态成员变量来实现的。静态成员变量占有自己独立的空间不为某个对象所私有。
问:友元关系有什么特性?
答:单向的,非传递的,不能继承的。
问:关键字volatile有什么含意?并给出三个不同的例子。
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1) 并行设备的硬件寄存器(如:状态寄存器)
2) 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3) 多线程应用中被几个任务共享的变量
回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。
假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1)一个参数既可以是const还可以是volatile吗?解释为什么。
2); 一个指针可以是volatile 吗?解释为什么。
3); 下面的函数有什么错误:
int square(volatile int *ptr)
{
        return *ptr * *ptr;
}
下面是答案:
1)是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2); 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3) 这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:
int square(volatile int *ptr)
{
    int a,b;
    a = *ptr;
    b = *ptr;
    return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:
long square(volatile int *ptr)
{
    int a;
    a = *ptr;
    return a * a;
}

问:  如何定义和实现一个类的成员函数为回调函数?

答:所谓的回调函数,就是预先在系统对函数进行注册,让系统知道这个函数的存在,以后,当某个事件发生时,再调用这个函数对事件进行响应。
定义一个类的成员函数时在该函数名前加CALLBACK即将其定义为回调函数,函数的实现和普通成员函数没有区别。
问:delete与 delete []区别:
delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数。
问:子类析构时要调用父类的析构函数吗?
参考答案1:析构函数调用的次序是先派生类的析构后基类的析构,也就是说在基类的的析构调用的时候,派生类的信息已经全部销毁了
参考答案2:程序结束之后当然所有的对象都会销毁,所以这个先析构派生类再析构基类是基于确定基类对象需要被销毁的时候进行的,但是当程序未结束,而一个派生类出了它的作用域的时候,这个时候仅仅调用子类的析构函数,而基类并不会被析构。
问:C++程序下列说法正确的有:
  A,对调用的虚函数和模板类都进行迟后编译.
  B,基类与子类中函数如果要构成虚函数,除了要求在基类中用virtual 声名,而且必须名字相同且参数类型相同返回类型相同
  C,重载的类成员函数都必须要:或者返回类型不同,或者参数数目不同,或者参数序列的类型不同.
  D,静态成员函数和内联函数不能是虚函数,友员函数和构造函数也不能是虚函数,但是析构函数可以是虚函数.
答:A
问:内联函数在编译时是否做参数类型检查?
  void g(base & b){
   b.play;
  }
  void main(){
   son s;
   g(s);
   return;
  }
问:已知String类定义如下:
class String
{
public:
  String(const char *str = NULL); // 通用构造函数
  String(const String &another); // 拷贝构造函数
  ~String(); // 析构函数
  String& operater =(const String &rhs); // 赋值函数
private:
char* m_data; // 用于保存字符串
};

尝试写出类的成员函数实现。
答案:
String::String(constchar*str)
{
if ( str == NULL ) // strlen在参数为NULL时会抛异常才会有这步判断
{
m_data =newchar[1] ;
m_data[0] ='\0' ;
}
else
{
m_data =newchar[strlen(str) +1];
strcpy(m_data,str);
}
}
String::String(const String &another)
{
m_data =newchar[strlen(another.m_data)+1];
strcpy(m_data,other.m_data);
}

String& String::operator=(const String &rhs)
{
if ( this==&rhs)
return*this ;
delete []m_data; //删除原来的数据,新开一块内存
m_data =newchar[strlen(rhs.m_data) +1];
strcpy(m_data,rhs.m_data);
return*this ;
}

String::~String()
{
delete []m_data ;
}
问:select函数的介绍
(1)一些小的知识点比如 select() 函数中第一个参数 int maxfdp 为什么要是最大的文件描述符的值 +1 ,当时临阵磨枪的看了下select函数,细致的知识点答不上来,参考http://blog.csdn.net/leo115/article/details/8097143

问:当一个类A 中没有申明任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。(Autodesk)
答案:肯定不是零。而是1。举个反例,如果是零的话,声明一个class A[10]对象数组,而每一个对象占用的空间是零,这时就没办法区分A[0],A[1]…了。
问:C++中一个类的大小如何确定?
这个以前没看过,就是分析了一下,结果露出了自己对虚函数理解的严重错误的马脚,接下来分析一下C++中类的大小:
(1)在一个C++类中,如果什么都没有,则这个类只占有1个字节;说明:如果一个类中没有任何数据成员,则这个类实际上是不占用存储空间的,size = 0;但是0不好在内存中定义一个地址,所以我们就人为的规定了大小为0的一个对象所占的存储空间的大小为1。
(2)一旦这个类中有其他的一些数据成员,比如说一个 int data ;那么这个类的大小就为 4 个字节,而不是5个字节,上述的一个字节不计算在内;
(3)普通的成员函数是不占用空间的,所以一个只用普通函数的类的大小只占有 1 个字节。说明:普通成员函数是类的所有对象所通用的方法,不算做对象的成员,所以不能算在对象的存储空间内。
(4)对于有虚函数的类,因为要存在一个虚函数表,需要4个字节,(是一个数组指针vptr,数组中存储的是虚函数的函数指针的地址),这个指向虚函数表的指针占用4个字节的存储空间。
(5)注意将数据对齐考虑进去,如一个类中含有 虚函数 和 一个char型数据,sizeof(class) = 8 ;默认对齐是 4字节对齐。
理解参考这个:http://blog.163.com/xping_lsr/blog/static/19654034520119804131721/

 

 _______________

_______________

整理笔记:

关于C++多态性 虚函数 纯虚函数与抽象基类 运算符重载

问:多态,虚函数,纯虚函数
多态:是对于不同对象接收相同消息时产生不同的动作。C++的多态性具体体现在运行和编译两个方面:在程序运行时的多态性通过继承和虚函数来体现;
在程序编译时多态性体现在函数和运算符的重载上
虚函数:在基类中冠以关键字 virtual 的成员函数。 它提供了一种接口界面。允许在派生类中对基类的虚函数重新定义。
纯虚函数的作用:在基类中为其派生类保留一个函数的名字,以便派生类根据需要对它进行定义。作为接口而存在 纯虚函数不具备函数的功能,一般不能直接被调用。
从基类继承来的纯虚函数,在派生类中仍是虚函数。如果一个类中至少有一个纯虚函数,那么这个类被称为抽象类(abstract class)。
抽象类中不仅包括纯虚函数,也可包括虚函数。l抽象类必须用作派生其他类的基类,而不能用于直接创建对象实例。但仍可使用指向抽象类的指针支持运行时多态性。
问:什么叫静态关联,什么叫动态关联
在多态中,如果程序在编译阶段就能确定实际执行动作,则称静态关联,
如果等到程序运行才能确定叫动态关联。
问:多态的两个必要条件
1.一个基类的指针或引用指向一个派生类对象,
2.虚函数
问:  多态的作用?
主要是两个:
1. 隐藏实现细节,使得代码能够模块化;扩展代码模块,实现代码重用;
2. 接口重用:为了类在继承和派生的时候,保证使用家族中任一类的实例的某一属性时的正确调用。
问: 虚函数是怎么实现的?
答:简单说来使用了虚函数表.
问:什么函数不能声明为虚函数?
答 构造函数(constructor)
Deconstructor 可以声明为虚函数。

问:聊了一下虚函数机制,虚函数表这一块理解的粗枝大叶,答得很狼狈:
(1)竟然理解成了 虚函数表中可以存储普通函数的函数指针地址,参考http://blog.csdn.net/leo115/article/details/8035078
(2)这个虚函数表是所有的类的实例都共用这个虚函数表呢?还是每个实例都会有一个虚函数表的copy版本?

问:怎样定义一个纯虚函数?含有纯虚函数的类称为什么?
在虚函数的后面加=0,含有虚函数的类称为抽象类。

问:纯虚函数是怎样实现的?在编译原理上讲一下?
在类内部添加一个虚拟函数表指针,该指针指向一个虚拟函数表,该虚拟函数表包含了所有的虚拟函数的入口地址,每个类的虚拟函数表都不一样,在运行阶段可以循此脉络找到自己的函数入口。
纯虚函数相当于占位符,先在虚函数表中占一个位置由派生类实现后再把真正的函数指针填进去。除此之外和普通的虚函数没什么区别。
问: 虚拟函数与普通成员函数的区别?内联函数和构造函数能否为虚拟函数?
答案:区别:虚拟函数有virtual关键字,有虚拟指针和虚函数表,虚拟指针就是虚拟函数的接口,而普通成员函数没有。内联函数和构造函数不能为虚拟函数。
问:抽象类为什么不能实例化?
抽象类中的纯虚函数没有具体的实现,所以没办法实例化。
问:抽象类不会产生实例,所以不需要有构造函数。 错
问:是不是一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态?
virtual修饰符会被隐形继承的。
virtual可加可不加,子类覆盖它的函数不加virtual ,也能实现多态。
问:函数重载是什么意思?它与虚函数的概念有什么区别?
函数重载是一个同名函数完成不同的功能,编译系统在编译阶段通过函数参数个数、参数类型不同,即实现的是静态的多态性。但是记住:不能仅仅通过函数返回值不同来实现函数重载。而虚函数实现的是在基类中通过使用关键字virtual来申明一个函数为虚函数,含义就是该函数的功能可能在将来的派生类中定义或者在基类的基础之上进行扩展,系统只能在运行阶段才能动态决定该调用哪一个函数,所以实现的是动态的多态性。它体现的是一个纵向的概念,也即在基类和派生类间实现。
问:构造函数和析构函数是否可以被重载,为什么?
答:构造函数可以被重载,析构函数不可以被重载。因为构造函数可以有多个且可以带参数,而析构函数只能有一个,且不能带参数。
问:运算符重载的意义?
答:为了对用户自定义数据类型的数据的操作与内定义的数据类型的数据的操作形式一致。
问:不允许重载的5个运算符是哪些?
答: .*(成员指针访问运算符号) ::域运算符  sizeof 长度运算符号   ?:条件运算符号  .(成员访问符)

问:运算符重载的三种方式?
答:普通函数,友元函数,类成员函数。
问:流运算符为什么不能通过类的成员函数重载?一般怎么解决?
答:因为通过类的成员函数重载必须是运算符的第一个是自己,而对流运算的重载要求第一个参数是流对象。一般通过友元来解决。

 

 _______________

_______________

整理笔记:

关于C++类的继承与派生 基类指针与派生类指针 虚基类

问:派生新类的过程要经历三个步骤
(1)吸收基类成员
(2)改造基类成员
(3)添加新成员
问:继承优缺点。
(1)类继承是在编译时刻静态定义的,且可直接使用,
(2)类继承可以较方便地改变父类的实现。
缺点:
(1)因为继承在编译时刻就定义了,所以无法在运行时刻改变从父类继承的实现
(2)父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类的行为
(3)如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。
问:怎样消除多重继承中的二义性?
(1)成员限定符
(2)虚基类

_______________

_______________

整理笔记:

关于C++模板  函数模板 类模板

问:C++中为什么用模板类。
答:(1)可用来创建动态增长和减小的数据结构
(2)它是类型无关的,因此具有很高的可复用性。
(3)它在编译时而不是运行时检查数据类型,保证了类型安全
(4)它是平台无关的,可移植性
(5)可用于基本数据类型
问:从一个模板类可以派生新的模板类,也可以派生非模板类。
答:对
问:函数模板与类模板有什么区别?
答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化必须由程序员在程序中显式地指定。

 

_______________

_______________

整理笔记:

关于C++输入输出流 文件的I O操作

问:c中的printf和c++中的cout有什么区别
printf是一个函数,而cout是一个对象。
C中的printf是一个标准的输出函数。C++中的cout是在iostrem文件中定义的全局对象
联系:完成的功能一样,都是输出。
区别:
1.书写格式不一样eg: 
int a=6;cout<<a<<endl;
printf("%d\n",a)
2.printf需要你告诉它格式(int %d, double %f,char %c), 而cout不需要
3.printf是函数。cout是ostream对象,和<<配合使用。
4.printf是变参函数,没有类型检查,不安全。cout是通过运算符重载实现的,安全。
5.如果printf碰到不认识的类型就没办法了,而cout可以自己重载进行扩展。
6.有时候printf比cout灵活。c++中也能使用printf,但是c中不能使用cout。
也可以这么说:c++可以完全兼容c的用法,反过来就不行 C++中的cout只要#include <iostream>就能生成此对象,便可直接使用。
C++能够定义全局变量,其实cout就相当于System.out对象。

问:系统会自动打开和关闭的3个标准的文件是?
(1)标准输入----键盘---stdin
(2)标准输出----显示器---stdout
(3)标准出错输出----显示器---stderr
问:如何打印出当前源文件的文件名以及源文件的当前行号?
答案:
cout << __FILE__ ;
cout<<__LINE__ ;
__FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。
问:联想笔试题
  1.设计函数 int atoi(char *s)。
  2.int i=(j=4,k=8,l=16,m=32); printf(“%d”, i); 输出是多少?

问: 编写strcat函数(6分)
已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc);
其中strDest 是目的字符串,strSrc 是源字符串。
要求:不调用C++/C 的字符串库函数,请编写函数 strcat.
答:
VC源码:
char * __cdecl strcat (char * dst, const char * src)
{
char * cp = dst;
while( *cp )
cp++; /* find end of dst */
while( *cp++ = *src++ ) ; /* Copy src to end of dst */
return( dst ); /* return dst */
}
问:已知strcpy函数的原型是:
        char * strcpy(char * strDest,const char * strSrc);
    1.不调用库函数,实现strcpy函数。
    2.解释为什么要返回char *。
解说:
    1.strcpy的实现代码
        char * strcpy(char * strDest,const char * strSrc)
        {
                if ((strDest==NULL)||(strSrc==NULL)) file://[/1]
                        throw "Invalid argument(s)"; //[2]
                char * strDestCopy=strDest;  file://[/3]
                while ((*strDest++=*strSrc++)!='/0'); file://[/4]
                return strDestCopy;
        }
    错误的做法:
    [1]
    (A)不检查指针的有效性,说明答题者不注重代码的健壮性。
    (B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。
    (C)检查指针的有效性时使用((strDest==0)||(strSrc==0)),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。
    [2]
    (A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。
    (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。
    [3]
    (A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。
    [4]
    (A)循环写成while (*strDest++=*strSrc++);,同[1](B)。
    (B)循环写成while (*strSrc!='/0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'/0'。多谢楼主  辛苦了

问:strlen函数如下:
#include<stdio.h>
#include<assert.h>
int strlen( constchar*str )//输入参数const
{
assert( str != NULL ); // 断言字符串地址非0
int len = 0;
while( (*str++) !='\0' )
{
len++;
}
return len;
}

函数头是这样的:
// pStr是指向以'\0'结尾的字符串的指针
// steps是要求移动的n
void LoopMove ( char* pStr,int steps )
{
 // 请填充...
}
 
解答:
正确解答1:
void LoopMove ( char*pStr, int steps )
{
 int n = strlen( pStr ) - steps;
 char tmp[MAX_LEN];
 strcpy ( tmp, pStr + n );
 strcpy ( tmp + steps, pStr);
 *( tmp + strlen ( pStr ) ) ='\0';
 strcpy( pStr, tmp );
}
 
正确解答2:
void LoopMove ( char*pStr, int steps )
{
 int n = strlen( pStr ) - steps;
 char tmp[MAX_LEN];
 memcpy( tmp, pStr + n, steps );
 memcpy(pStr + steps, pStr, n );
 memcpy(pStr, tmp, steps );
}
剖析:
  这个试题主要考查面试者对标准库函数的熟练程度,在需要的时候引用库函数可以很大程度上简化程序编写的工作量。
最频繁被使用的库函数包括:
(1) strcpy
(2) memcpy
(3) memset

问:strcpy()和memcpy()的区别?
strcpy()和memcpy()都可以用来拷贝字符串,strcpy()拷贝以’\0’结束,但memcpy()必须指定拷贝的长度。
问:strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值?
答:方便赋值给其他变量

问:memset ,memcpy 的区别
memset用来对一段内存空间全部设置为某个字符,一般用在对定义的字符串进行初始化为'\0'。
memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;

——————————————————————————

————————————————————————————

填空题

213 C++语言是在___ C ______语言的基础上发展起来的。
214 C++语言的编译单位是扩展名为____ .cpp______的____程序______文件。
215. 行尾使用注释的开始标记符为____ //_____。
216 多行注释的开始标记符和结束标记符分别为_____ /*_____和___ */_______。
217. 用于输出表达式值的标准输出流对象是____ cout_____。
218 用于从键盘上为变量输入值的标准输入流对象是__ cin______。
219. 一个完整程序中必须有一个名为____ main____的函数。
220一个函数的函数体就是一条____复合_____语句。
221. 当执行cin语句时,从键盘上输入每个数据后必须接着输入一个___空白_____符,然后才能继续输入下一个数据。
222. 在C++程序中包含一个头文件或程序文件的预编译命令为____#include ______。
223. 程序中的预处理命令是指以___#___字符开头的命令。
224. 一条表达式语句必须以___分号___作为结束符。
225. 在#include命令中所包含的头文件,可以是系统定义的头文件,也可以是___用户(或编程者_____定义的头文件。
226. 使用#include命令可以包含一个头文件,也可以包含一个__程序____文件。
227.一个函数定义由__函数头______和__函数体_____两部分组成。
228.若一个函数的定义处于调用它的函数之前,则在程序开始可以省去该函数的__原型(或声明)____语句。
229.C++头文件和源程序文件的扩展名分别为__.h ___和___.cpp ___。
230.程序文件的编译错误分为____警告(warning)____和____致命(error) ____两类。
231.当使用___ void ____保留字作为函数类型时,该函数不返回任何值。
232.当函数参数表用___ void __保留字表示时,则表示该参数表为空。
233.从一条函数原型语句“int fun1(void);”可知,该函数的返回类型为__int____,该函数带有___0___个参数。
234. 当执行cout语句输出endl数据项时,将使C++显示输出屏幕上的光标从当前位置移动到___下一行_____的开始位置。
235. 假定x=5,y=6,则表达式x++*++y的值为___35_______。
236. 假定x=5,y=6,则表达式x--*--y的值为___25_______。
237. 假定x=5,y=6,则执行表达式y*=x++计算后,x和y的值分别为___6___和___30 _____。
238. 假定x=5,y=6,则执行表达式y+=x--计算后,x和y的值分别为____4__和___11___。
239. C++常数0x145对应的十进制值为___325 ___。
240. C++常数0345对应的十进制值为____ 229__。
241. 十进制常数245对应的十六进制的C++表示为____0xF5___。
242. 十进制常数245对应的八进制的C++表示为___0365 ___。
243. signed char类型的值域范围是__-128__至___+127 __之间的整数。
244. int和float类型的数据分别占用___ 4___和____ 4___个字节。
245. float和double类型的数据分别占用____ 4___和_____8___个字节。
246. bool和char类型的数据分别占用_____1____和____1___个字节。
247. unsigned short int和int类型的长度分别为____ 2___和____4___。
248. 字符串”This\’s a book.\n”的长度为_____ 15____。
249. 字符串”\nThis\’s a pen\n\n”的长度为_____ 15_____。
250. 在C++中存储字符串”abcdef”至少需要___7 _____个字节。
251. 在C++中存储字符串”a+b=c”至少需要_____6 ___个字节。
252. 假定x和y为整型,其值分别为16和5,则x%y和x/y的值分别为___1_______和____3____。
253. 假定x和y为整型,其值分别为16和5,则x/y和double(x)/y的值分别为____3____和___3.2____。
254. 假定x是一个逻辑量,则x && true的值为___ x ____。
255. 假定x是一个逻辑量,则x || true的值为_____ true(或1)_____。
256. 假定x是一个逻辑量,则x && false的值为____ false(或0) ___。
257. 假定x是一个逻辑量,则x || false的值为x。
258. 假定x是一个逻辑量,则!x || false的值为____!x ____。
259. 假定x是一个逻辑量,则x && !x的值为____ false(或0)____。
260. 假定x是一个逻辑量,则x || !x的值为____ true(或1)___。
261. 设enum Printstatus{ready,busy,error}; 则 cout<<busy的输出结果是_____1___。
262. 设enum Printstatus{ready=2,busy,error}; 则cout<<busy的输出结果是____3____。
263. 常数-4.205和6.7E-9分别具有___4_____和____2___位有效数字。
264. 枚举类型中的每个枚举值都是一个____枚举常量_____,它的值为一个___整数____。
265. 常数100和3.62的数据类型分别为____ int ___和_____ double ___。
266. 若x=5, y=10, 则计算y*=++x表达式后,x和y的值分别为___6___和__60 ___。
267. 假定x和ch分别为int型和char型,则sizeof(x)和sizeof(ch)的值分别为__4__和__1__。
268. 假定x=10,则表达式x<=10?20:30的值为__ 20 __。
269. 表达式sqrt(81)和pow(6,3)的值分别为___9 ___和___216___。
270. 含随机函数的表达式rand()%20的值在___0__至___ 19 __区间内。
271. 在switch语句中,每个语句标号所含关键字case后面的表达式必须是___常量___。
272. 在if语句中,每个else关键字与它前面同层次并且最接近的____ if ____关键字相配套。
273. 作为语句标号使用的C++保留字case和defaule只能用于___ switch ___语句的定义体中。
274. 执行switch语句时,在进行作为条件的表达式求值后,将从某个匹配的标号位置起向下执行,当碰到下一个标号位置时(停止/不停止)___不停止__执行。
275. 若while循环的“头”为“while(i++<=10)”,并且i的初值为0,同时在循环体中不会修改i的值,则循环体将被重复执行__11___次后正常结束。
276. 若do循环的“尾”为“while(++i<10)”,并且i的初值为0,同时在循环体中不会修改i的值,则循环体将被重复执行___10 ___次后正常结束。
277. 当在程序中执行到break语句时,将结束本层循环类语句或switch语句的执行。
278. 当在程序中执行到___ continue___语句时,将结束所在循环语句中循环体的一次执行。
279. 在程序中执行到__ return ___语句时,将结束所在函数的执行过程,返回到调用该函数的位置。
280.在程序执行完____主(或main)__函数调用后,将结束整个程序的执行过程,返回到C++集成开发窗口。
281. 元素类型为int的数组a[10]共占用___ 40___字节的存储空间。
282. 元素类型为double的二维数组a[4][6]共占用____192__字节的存储空间。
283. 元素类型为char的二维数组a[10][30]共占用___300__字节的存储空间。
284. 存储字符’a’和字符串”a”分别需要占用_____1___和____2 ___个字节。
286. 以面向对象方法构造的系统,其基本单位是_____对象___。
287. 每个对象都是所属类的一个__实例__。
288. C++支持两种多态性:___编译____时的多态性和____运行__时的多态性。
289. 在C++中,编译时的多态性是通过___重载___实现的,而运行时的多态性则是通过___虚函数____实现的。
290. 对于类中定义的任何成员,其隐含访问权限为___ private(或私有)__。
291. 对于结构中定义的任何成员,其隐含访问权限为__ public(或公有)_。
292. 若在类的定义体中给出了一个成员函数的完整定义,则该函数属于__内联__函数。
293. 为了避免在调用成员函数时修改对象中的任何数据成员,则应在定义该成员函数时,在函数头的后面加上__ const __关键字。
294. 若只需要通过一个成员函数读取数据成员的值,而不需要修改它,则应在函数头的后面加上__ const __关键字。

 

参考资料:

http://   blog.sina.com.cn/s/blog_606f9bd70100e51g.html 堆栈溢出

http://  blog.csdn.net/shengliz/article/details/5345124 C++面试经常涉及的概念1

http://  tieba.baidu.com/p/1597784148  基本概念及其它问答题

C++面试题汇总贴
面试题http://blog.csdn.net/leo115/article/details/8111926
华为笔试题http://wenku.baidu.com/link?url=Cdzuv3mQuUWF_hIkACWvKHvZigj3qg08WGMl4T3FiDg0H1nER5XpNqFinPxnUbGVmxqr1B9qIy7U1KGVGo42BIIdOYbwTysCpo_i9s1ncKS
面试宝典大全 http://wenku.baidu.com/link?url=ndaip1BaGc6H7AQk7iN5JcPsZW9sznrII-Iv7TmMIgav3MANzx9X4sCpdCLFs7-buLb8xeXQW-ESQzhPg9V3ncYrQQ2sigeViIJ7oob0ApG
C++面试题 http://www.sf.org.cn/Article/base/200803/20885.html
C++面试题 http://blog.csdn.net/jingxuewang110/article/details/6789557/
C++面试题目大全 http://wenku.baidu.com/view/84d428db7f1922791688e8d7.html
c​ ​c​+​+​面​试​题​3​0​0 http://wenku.baidu.com/view/c330da88680203d8ce2f24dd.html

 

0 0
原创粉丝点击