1、.h头文件中的ifndef/define/endif的作用?
防止该头文件被重复引用。
2、#include<file.h>与#incude“file.h”的区别?
#include<file.h>:编译器从标准库路径开始搜索和引用file.h;
#include“file.h”:编译器从当前工作路径搜索并引用file.h;
3、在C++程序中调用被C编译器编译后的函数,为什么要加extern "C"?
由于C++支持函数重载,C语言不支持函数重载,函数被C++编译后在库中的名字与C语言不同。假设某个函数的原型为 void foo(int x,int y);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号extern "C"来解决名字匹配问题。
extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言的进行编译,而不是C++的。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般之包括函数名。这个功能十分有用处,因为在C++出现以前,很多代码都是C语言写的,而且很底层的库也是C语言写的,为了更好的支持原来的C代码和已经写好的C语言库,需要在C++中尽可能的支持C,而extern "C"就是其中的一个策略。 这个功能主要用在下面的情况: 1、C++代码调用C语言代码 2、在C++的头文件中使用 3、在多个人协同开发时,可能有的人比较擅长C语言,而有的人擅长C++,这样的情况下也会有用到。
4、面向对象的三个基本特征,并简单叙述之?
(1)封装:将客观事物抽象成类,每个类对自身的数据和方法实行protection(private, protected,public)
(2)继承:广义的继承有三种实现形式:实现继承(指使用基类的属性和方法而无需额外编码的能力)、可视继承(子窗体使用父窗体的外观和实现代码)、接口继承(仅使用属性和方法,实现滞后到子类实现)。前两种(类继承)和后一种(对象组合=>接口继承以及纯虚函数)构成了功能复用的两种方式。
(3)多态 :系统能够在运行时,能够根据其类型确定调用哪个重载的成员函数的能力,称为多态性。(见:C++中类的多态与虚函数的使用)
5、引用与指针有什么区别?
1) 引用必须被初始化,指针不必。 2) 引用初始化以后不能被改变,指针可以改变所指的对象。 3) 不存在指向空值的引用,但是存在指向空值的指针。
6、描述实时系统的基本特性?
在特定的时间完成特定的任务,实时性与可靠性。
7、全局变量与局部变量是否有区别,如果有,什么区别?
全局变量储存在静态数据区,局部变量存储在堆栈中。
8、堆栈溢出一般是由什么原因导致的?
没有回收垃圾资源
9、什么函数不能声明为虚函数?
构造函数
10、IP地址的编码分为哪两部分?
IP地址由两部分组成,网络号和主机号
11、不能做switch()的参数类型的是:
switch()的参数类型不能为实型。
12、对于一个频繁使用的短小函数,在C语言中应用什么实现?在C++中应用什么实现?
在C语言中,用宏定义;在C++中用inine 。
13、C++是不是类型安全的?
不是类型安全的,两个不同类型的指针之间可以强制转换。
14、指针和数组的区别?
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。指针可以随时指向任意类型的内存块。
15、内存的分配方式?
分配方式有三种:(1)静态存储区,是在程序编译时就已经分配好的,在整个程序运行期间都存在,如全局变量和常量。(2)栈上分配,函数内的局部变量就是从这分配的,但是分配的内存有限。(3)堆上分配:也称动态分配,如我们用的new 和malloc分配内存,delete和free释放内存。
16、C++中值的传递方式:
值传递、指针传递、引用传递
19、数组在做函数实参时会变成什么类型?
会变成指针类型
20、在Win32下,char、int、float以及double各占几个字节?
char :1个字节
int:4个字节
float :4个字节
double: 8个字节
21、简述debug和release版本的区别?
debug是调试版本,release是发布给用户的最终非调试版本。
22、class和struct的区别?
struct的成员默认是公有的。而类的成员默认是私有的。
23、当一个类A中没有任何成员变量和成员函数时,这是sizeof(A)的值是多少?并解释编译器为什么没有让它为0?
此时sizeof(A)=1;举个反例:如果是0的话,声明一个class A[10]对象数组,而每一个对象占用的空间为0,这时就没有办法区分A[0],A[1]......了
24、请写出BOOL flag与“零值”比较的if语句。
if(flag)或者if(!flag)
25、请写出float x与int y与“零值”比较的if语句。
float: const float EPSINON=0.000001;
if((x>=-EPSINON)&&(x<=EPSINON))
int: if(y==0)
26、请写出char *p与“零值”比较的if语句。
if(p==NULL)
if(p!=NULL)
27、以下为Windows下的32位C++应用程序,请计算sizeof的值。
先对sizeof作一下简要的说明:
(1)sizeof不是一个函数 只是一个操作符,像new和delete一样。
(2)char *s是一个指针,所以sizeof(s)的结果是s指针本身所占用的真实空间4个字节。strlen(s)才是求s指向的字符串的长度。
(3)若操作数具有类型char、unsigned char或signed char时,结果为1。
(4)当sizeof作用于一个class 、struct时,返回这些类型对象所占字节数。当一个类A中没有任何数据成员和成员函数时,sizeof(A)=1;
(5)char a[100];对于32位程序,sizeof(a)=4;对于64位程序,sizeof(a)=8;而不是100;
test sizeof代码如下:
#include<iostream>
using namespace std;
int main()
{
char str[]="hello";
char *p=str;
int i=100;
float f=0.4;
double d=4.21;
cout<<"sizeof(str)="<<sizeof(str)<<endl;
cout<<"sizeof(p)="<<sizeof(p)<<endl;
cout<<"strlen(p)="<<strlen(p)<<endl;
cout<<"sizeof(i)="<<sizeof(i)<<endl;
cout<<"sizeof(f)="<<sizeof(f)<<endl;
cout<<"sizeof(d)="<<sizeof(d)<<endl;
cout<<"str[0]="<<str[0]<<endl;
cout<<"sizeof(str[0])="<<sizeof(str[0])<<endl;
void *p1=malloc(100);
cout<<"sizeof(p1)="<<sizeof(p1)<<endl;
}
结果如下:
若将上面的代码更改为64位C++代码,结果如下:
sizeof(p)和sizeof(p1)由32位下的4变成了8。
28、const有什么用途?(至少写两种)
(1)可以定义const常量。
(2)可以修饰函数的参数、返回值、甚至函数的定义体,被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
29、编写类String的构造函数、析构函数和赋值函数。
已知类String的原型为:
class String
{
public:
String(const char *str=NULL);//普通构造函数
String(const String & other);//拷贝构造函数
~String(void);
String &operator=(const String &other);//赋值函数
private:
char *m_data;
};
详见如下示例代码:
#include<iostream>
using namespace std;
//
char *STRCPY(char *strDest,const char *strSrc)
{
_ASSERT((strDest!=NULL)&&(strSrc!=NULL));
char *address=strDest;
while((*strDest++=*strSrc++)!='\0')//'\0'是终止符,当编译器看到它,就会认为字符串已结束了。
NULL;
return address;
}
class String
{
public:
String(const char *str=NULL);//普通构造函数
String(const String & other);//拷贝构造函数
~String(void);//析构函数
String &operator=(const String &other);//赋值函数
private:
char *m_data;
};
String::String(const char *str)
{
cout<<"Constructing"<<endl;
if(str==NULL)
{
m_data=new char[1];
*m_data='\0';
}
else
{
m_data=new char[strlen(str)+1];
STRCPY(m_data,str);
}
}
String::String(const String & other)
{
cout<<"Constructing copy"<<endl;
m_data=new char[strlen(other.m_data)+1];
STRCPY(m_data,other.m_data);
}
String &String::operator=(const String &other)
{
cout<<"Operate = Function"<<endl;
if(this==&other)//如果对象与other是同一个对象,直接返回本身
{
return *this;
}
delete[]m_data;
m_data=new char[strlen(other.m_data)+1];
STRCPY(m_data,other.m_data);
return *this;
}
String::~String(void)
{
cout<<"Destructing"<<endl;
if(m_data!=NULL) //如果m_data不为NULL,释放堆内存
{
delete []m_data;
m_data=NULL;
}
}
int main()
{
String obj1("hello");//调用普通构造函数
String obj2("world");//调用普通构造函数
String obj3(obj1);
obj3=obj2;
return 0;
}
结果如下:
30、简述以下两个for循环的优缺点。
(1)
for(int i=0;i<N;i++)
{
if(condition)
DoSomething();
else
DoOtherThing();
}
(2)
if(condition)
{
for(int i=0;i<N;i++)
DoSomething();
}
else
{
for(int i=0;i<N;i++)
DoOtherThing();
}
(1)优点:程序简洁;
缺点:比(2)多执行了N-1次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了程序的效率。
(2) 优点:循环效率高
缺点:程序不简洁
31、编写strcpy函数。
已知strcpy函数的原型为char *strcpy(char *strDest,const char *strSrc); 其中strDest为目的字符串,strSrc为源字符串。
(1)不调用C/C++的字符串库函数,请编写strcpy,详见29中的STRCPY函数。
(2)strcpy能把strSrc的内容复制到strDest,为什么还要char *类型的返回值?
为了实现链式表达式
例如:int length=strlen(strcpy(strDest,"hello world"));
31、CMemoryState的主要功能是什么?
查看内存使用情况,解决内存泄漏问题。
32、处理器标识#error的目的是什么?
编译器输出一条错误信息,并终止继续编译。
33、在定义一个宏的时候应注意些什么?
定义部分的每个形参和整个表达式都必须用括号括起来,以避免不可预料的事情发生。
34、系统会自动打开和关闭的三个标准文件是什么?
标准输入--键盘--stdin
标准输出--显示器--stdout
标准错误输出--显示器-stderr
35、static有什么用途?
(1)在函数体内,一个被声明为静态的变量在函数被调用的过程中维持其值不变;
(2)在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所有函数调用,但不能被模块外的函数所调用。
(3)在模块内,一个被声明为静态的函数只可被该模块内的其他函数调用,也就是该函数被限制在声明它的模块内的本地范围内使用。