C/C++面试题

2017-04-02 21:49:02    面试经验   

1、指针和引用的区别?

答:引用是在C++中引入的。它们之间的区别有:

(1)       非空区别:指针可以为空,而引用不能为空

(2)       可修改区别:如果指针不是常指针,那么就可以修改指向,而引用不能

(3)       初始化区别:指针在定义时可以不用初始化,而引用在定义的同时必须初始化

2、为什么构造函数不能声明为虚函数?

答:因为虚函数采用的是虚调用的方法,虚调用是指允许在只知道部分信息的情况下的工作机制,特别允许我们调用一个只知道接口而不知道其对象的准确类型的函数。但是如果我们要调用构造函数创建对象时,必须要知道对象的准确类型,因此构造函数不能为虚函数。

3、char str1[]=”abc”; char str2[] = “abc”;   str1==str2为FALSE,因为str1和str2是位于堆栈上的,它们占用不同的内存空间。Const char str3[] = “abc”; const char str4[] = “abc”;str3==str4为FALSE,同样它们是位于堆栈上的内存空间,是不同的。Const char *str5=”abc”, const char *str6=”abc”;char *str7=”abc”,char *str8 = “abc”,str5==str6 str7==str8为TRUE,因为”abc”是位于文字常量区的,系统会将几个“abc”进行优化,使它们位于同一块内存区,因此指针的指向也就相同了。

4、以下函数能求出数组的长度吗?

void fun(char str[])

{

       int len = sizeof(str)/sizeof(str[0]);

}

答:不能,数组作为参数传递给函数时,数组名被退化为指针,因此函数中的sizeof(str)实际是在求一个指针的sizeof,答案为4,因此不能计算出数组的长度。

5、一个32位的机器,该机器的指针是多少位?

答:指针是多少位只要看地址总线的位数就行了,80386以后的机子都是32的数据总线。所以指针的位数就是4个字节。即有void *p; 则sizeof(p) = 4。

6、C和C++中的struct和class有什么不同?

答:C和C++中struct的区别是C中的struct不能有成员函数,而C++中的struct可以。C++中struct和class的主要区别是默认的存取权限,struct的默认存取权限为public,而class的默认存取权限为private。

7、类的静态成员和非静态成员有何区别?

答:类的静态成员每个类只有一个,静态成员为所有类的实例对象共享,静态成员有静态成员变量和静态成员函数,静态成员变量使用前必须初始化,静态成员变量可以被静态成员函数和非静态成员函数访问,而静态成员函数只能访问静态成员变量,因为静态成员函数属于类,其没有this指针。非静态成员每个对象都有一个。

8、纯虚函数的定义?

答:virtual void fun()=0;含有纯虚函数的类为抽象类,抽象类不能实例化对象,但是可以定义指针,纯虚函数是接口,由子类实现。

9、请讲一讲析构函数和虚函数的用法和作用?

答:析构函数是用于在撤销对象时完成对对象的清理工作,比如在创建对象时,如果在构造函数中动态申请了内存,那么在对象释放时,应该在析构函数中对动态申请的内存进行释放,避免造成内存泄露,如果在这个时候还不释放就没有机会释放内存了,会造成内存泄露,总之需要在释放对象之前完成的工作都可以放在析构函数中完成,析构函数不需要用户显示调用,它会在释放对象前由系统自动调用。虚函数是实现多态性的方式,虚函数在子类中被重写,因此可以通过基类指针调用不同子类的虚函数,实现一个接口,多种实现。正是因为多态性的存在,为了使子类的析构函数随时都能够执行,基类的析构函数一般都声明为虚析构函数。

10、全局变量和局部变量有什么区别?是怎么实现的?操作系统和编译器是怎么知道的?

答:区别在于它们的作用域不同,全局变量可以在整个程序被使用,局部变量只能在子程序或函数中使用,函数执行完后,局部变量的也被销毁了。操作系统和编译器可能是通过它们所分配的内存区来知道的,全局变量被放在全局数据区,而局部变量放在堆栈中。

11、若类A和类B没有继承关系,对于函数void func(A&),请至少用两种不同方法说明如何才能传递一个非常量的B类对象非func函数。

答:可在A类中定义一个构造函数 A(const B&)

       或在B类中定义一个自动转换函数:operator A() const

12、static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?

答:static全局变量与普通的全局变量的区别:前者在主函数之前就要被初始化,而后者没有要求,两者的作用域不同,前者的作用域只限于子模块(子程序或函数),而后者在整个程序中都可以被使用。

       static局部变量和普通局部变量的区别:一个函数中的static变量值会保留到该函数下次调用来改变它,而后者在函数运行完后就被销毁了,两者的存储区域不同,前者存储在静态区(全局区),后者的内存位于堆栈上。

       static函数与普通函数:static函数可以直接通过类调用,不需要在此之前实例化对象,而普通函数需要先定义对象。static函数不能用非static成员。static在循环中定义并赋值时,定义过程只进行一次,而不是每个循环1次。

13、写程序,从键盘上输入一系列整数,以输入-1为结束,将输入的数据保存到文件data.txt中。

答:C语言实现:

#include <stdio.h>

int main()

{

       FILE *fp;

       if ((fp=fopen("data.txt","wb")) == NULL)

       {

              cout<<"open error"<<endl;

              exit(1);

       }

       int x;

       scanf(“%d”, &x);

       while (x!=-1)

       {

              fputc(x, fp);

              cin>>x;

       }

       fclose(fp);

       return 0;

}

C++实现:

#include <iostream>

#include <fstream>

using namespace std;

int main()

{

       ofstream fout("data1.txt");

       if (!fout)

       {

              exit(1);

       }

       int x;

       cin>>x;

       while (x != -1)

       {

              fout<<x<<' ';

              cin>>x;

       }

       fout.close();

       return 0;

}

14、写程序,将一个字符串倒序?

答:直接在main函数中实现的

void main()

{

char *source = "hello";

       char *des;

       int len = strlen(source);

       des = (char *)malloc(len+1);  //申请空间必须是len+1,加1是为了放结束符

       if (!des)

       {

              exit(1);

       }

       char *s = &source[len-1];

       char *d = des;

       while (len--!=0)

       {

              *d++ = *s--;

       }

       *d = '\0';  //必须要

       cout<<source<<endl;

       cout<<des<<endl;

}

15、static的用途?

答:(1)函数体内的静态变量,其值在函数的调用过程中保持不变。跟局部变量的区别。

   (2)在函数体外定义的静态变量,限制了它的使用范围只在于该子模块,该子模块内的函数都能访问它,但是子模块外不能访问,实际就类似于是一个本地的全局变量。与一般全局变量的区别。

  (3)类的静态成员函数。

       本质上来说,static就是声明了对象的生成期,限制了对象的作用域。

或 (1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只能被分配一次,因此其值在下次函数调用时仍维持上次的值。

   (2)在模块内的static全局变量可以被模块内的所有函数访问,但不能被模块外其他函数访问。

   (3)在模块内的static函数只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块。

   (4)在类中的static成员变量属于整个类所有,对类的所有对象只有一份拷贝。

   (5)在类中的static成员函数属于整个类所有,这个函数不接受this指针,因而只能访问类的static成员变量。

16、在C++程序中调用C编译后的函数,为什么要加extern C的声明?

答:因为C++支持函数重载,而C不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。假设某个函数的原型为:void foo(int x, int y);该函数被C编译器编译后在库中的名字为_foo,而C++编译器则产生像_foo_int_int之类的名字。C++提供了C连接交换指定符号 extern C来解决名字匹配问题。

17、float x与零值的比较,指针p与NULL的比较,布尔变量flag与TRUE的比较

答:(1)const float EPSION = 0.00001;

              if (x >= -EPSION && x <= EPSION)

       (2) if (p == NULL)

       (3) if (flag)

18、C++中哪些函数不能被声明为虚函数?

答:普通函数(非成员函数),构造函数,内联成员函数、静态成员函数、友元函数。

(1)虚函数用于基类和派生类,普通函数所以不能

(2)构造函数不能是因为虚函数采用的是虚调用的方法,允许在只知道部分信息的情况的工作机制,特别允许调用只知道接口而不知道对象的准确类型的方法,但是调用构造函数即使要创建一个对象,那势必要知道对象的准确类型。

(3)内联成员函数的实质是在调用的地方直接将代码扩展开

(4)继承时,静态成员函数是不能被继承的,它只属于一个类,因为也不存在动态联编等

(5)友元函数不是类的成员函数,因此也不能被继承

19、include <filename.h>和include “filename.h”的区别?

答:<>是从标准库路径搜索, “”是从用户当前工作目录开始,找不到,在到标准库开始

20、void GetMemory(char **p, int num)

{  

*p = (char *)malloc(num);

}

void Test(void)

{

char *str = NULL;

GetMemory(&str, 100);

strcpy(str, "hello");

printf(str);

}

请问运行Test 函数会有什么样的结果?

答:输出“hello”, 注意GetMemory函数中的p参数是指向指针的指针,如果是一级指针则出现错误,不会得到申请的地址空间。

21.void GetMemory(char *p, int num)

{  

*p = (char *)malloc(num);

}

void Test(void)

{

char *str = NULL;

GetMemory(str, 100);

strcpy(str, "hello");

printf(str);

}

请问运行Test 函数会有什么样的结果?

答:运行出错,注意与20中参数p的类型比较,20中是char **p,而本题是char *p。而且像这种情况还会导致每次都泄露一块内存的危险。

22、char *GetMemory(void)

{

char p[] = "hello world";

return p;

}

void Test(void)

{

char *str = NULL;

str = GetMemory();

printf(str);

}

请问运行Test 函数会有什么样的结果?
答:无效的指针,输出不确定,因为p是函数GetMemory中申请的是一个临时变量,函数调用完后,其空间已经不再存在。

23.char *GetMemory3(int num)

{

char *p = (char *)malloc(sizeof(char) * num);

return p;

}

void Test3(void)

{

char *str = NULL;

str = GetMemory3(100);

strcpy(str, "hello");

cout<< str << endl;

free(str);

}

请问运行Test 函数会有什么样的结果?
答:输出”hello”,因为是返回动态申请的内存,只要不释放内存,即调用free函数,就可以使用该段内存。

24.char *GetString2(void)

{

char *p = "hello world";

return p;

}

void Test5(void)

{

char *str = NULL;

str = GetString2();

cout<< str << endl;

}

答:函数Test5运行虽然不会出错,但是函数GetString2的设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。如果此时还想利用strcpy往str中写数据时,将出现错误。如strcpy(str,”hello world”)。

25、编写strlen函数

答:

int Strlen(const char *str)

{

int len = 0;

         assert(str != NULL);

         while (*str++ != '\0')

         {

                   len++;

         }

         return len;}

非空判断是必须进行的操作,可以使用断言的方式assert(str) != NULL才会继续

26、编写strcpy函数

答:  char *StrCopy(char *strDes, const char *strSrc)

{

       assert((strDes != NULL) && (strSrc != NULL));  

       char *address = strDes;

       while ((*strDes++ = *strSrc++) != '\0')

QQ
微信
公众号
扫一扫
客服