C++试题

来源:互联网 发布:js判断数组拼接 编辑:程序博客网 时间:2024/05/19 18:39
 一、简答题。
1. 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,内存泄漏 
 
2. char *GetMemory(void) 
{    
char p[] = "hello world"; 
return p; 

void Test(void) 

char *str = NULL; 
str = GetMemory();     
printf(str); 

请问运行 Test函数会有什么样的结果? 
 
最佳答案是:可能是乱码。因为 GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但
其原现的内容已经被清除,新内容不可知。 
 
3. void GetMemory(char *p) 

p = (char *)malloc(100); 

void Test(void)  

char *str = NULL; 
GetMemory(str);      
strcpy(str, "hello world"); 
printf(str); 

请问运行 Test函数会有什么样的结果? 
最佳答案是:程序崩溃。 因为 GetMemory并不能传递动态内存, Test函数中的 str一直都是 NULL。 strcpy(str, 
"hello world");将使程序崩溃。 
 
4. void Test(void) 

char *str = (char *) malloc(100); 
    strcpy(str, "hello"); 
    free(str);       
    if(str != NULL) 
    { 
      strcpy(str, “world”);  
printf(str); 


请问运行 Test函数会有什么样的结果? 
最佳答案是:篡改动态内存区的内容,后果难以预料,非常危险。因为 free(str);之后, str成为野指针, if(str != 
NULL)语句不起作用。 
 
二、问答题。
1. !解释:基类与派生类对象之间赋值兼容原则 
最佳答案是:基类对象与派生类对象之间赋值兼容原则:一个公有派生类的对象在使用上可以被当作基类的
对象,反之则禁止。也就是说: (1)可以将派生类的对象赋值给基类对象,反之不对;结果:只是将从基
类继承过来的成员赋值,基类对象只能访问派生类中从基类继承的公有成员,不能访问派生类中增加的公有
成员。 (2)派生类的对象可以初始化基类的引用;结果:基类对象只能引用派生类从基类继承的成员。 (3)
指向基类的指针也可以指向派生类(即可以将一个派生类的对象赋值给基类的指针)。结果:基类的指针
只能引用从基类继承来的成员。!
 
2.C++继承是如何工作的 
 
最佳答案是:答:继承使得派生类能够使用基类的公有和保护成员,从而实现代码的复用,派生类可以增加
成员,也可以隐藏和覆盖基类的成员。对于公有继承,基类成员的访问权限在派生类保持不变。 
 
3. 拷贝构造函数在哪几种情况下调用 
 
最佳答案是: 用一个对象初始化另一个对象时当用对象作为函数参数传递时当函数返回对象时 
 
4. 多态,虚函数,纯虚函数的概念。 
最佳答案是: 
多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,
可以通过指向基类的指针,来调用实现派生类中的方法。 
虚函数:在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数。 
纯虚函数:纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有
意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函
数的作用。 
 
 
5. 什么叫做抽象类?抽象类有何作用?抽象类的派生类是否一定要给出纯虚函数? 
最佳答案是:  
抽象类的主要作用是通过它为一个类族+建立一个公共的接口,使它们能够更有效地发挥多态特性。抽
象类声明了+一组派生类共同操作接口的通用语义,而接口的完整实现, +即纯虚函数的函数体,要由派生
类自己给出。但抽象类的派生+类并非一定要给出纯虚函数的实现,如果派生类没有给出纯虚函数的实现,
+这个派生类仍然是一个抽象类&aq=f&oq=带有纯虚函数的类是抽象类。抽象类的主要作用是通过它为一
个类族+建立一个公共的接口,使它们能够更有效地发挥多态特性。抽象类声明了+一组派生类共同操作接
口的通用语义,而接口的完整实现,+即纯虚函数的函数体,要由派生类自己给出。但抽象类的派生+类并
非一定要给出纯虚函数的实现,如果派生类没有给出纯虚函数的实现,+这个派生类仍然是一个抽象类 
 
 
6. 在 C++语言中,能否声明虚构造函数?为什么?能否声明虚析构函数?有何用途?  
最佳答案是:解释一:所谓虚函数就是多态情况下只执行一个。而从继承的概念来讲,总是要先构造父类对
象,然后才能是子类对象。如果构造函数设为虚函数,那么当你在构造父类的构造函数时就不得不显示的
调用构造。还有一个原因就是为了防错,试想如果你在子类中一不小心重写了个跟父类构造函数一样的函
数,那么你的父类的构造函数将被覆盖,也即不能完成父类的构造.就会出错。解释二:虚函数的主要意义
在于被派生类继承从而产生多态。派生类的构造函数中,编译器会加入构造基类的代码,如果基类的构造
函数用到参数,则派生类在其构造函数的初始化列表中必须为基类给出参数,就是这个原因。虚函数的意
思就是开启动态绑定,程序会根据对象的动态类型来选择要调用的方法。然而在构造函数运行的时候,这
个对象的动态类型还不完整,没有办法确定它到底是什么类型,故构造函数不能动态绑定。(动态绑定是
根据对象的动态类型而不是函数名,在调用构造函数之前,这个对象根本就不存在,它怎么动态绑定?)
编译器在调用基类的构造函数的时候并不知道你要构造的是一个基类的对象还是一个派生类的对象。析构
函数设为虚函数的作用: 解释:在类的继承中,如果有基类指针指向派生类,那么用基类指针 delete时,
如果不定义成虚函数,派生类中派生的那部分无法析构。 
 
7.说出以下三种函数中分别可以抛出什么异常 
void f(); 
void f() throw() 
intfunc( int x ) throw( int, Error_message) 


最佳答案是: void f()可能抛出任何类型的异常 
void f() throw()不抛出任何类型的异常 
Intfunc(int x)throw(int, Error_message)抛出 int类型或者 Error_message类型异常 
8. 什么是动态绑定,动态绑定有什么好处 
最佳答案是:C++中,通过基类的引用或指针调用虚函数时,发生动态绑定。引用(或指针)既可以指向
基类对象也可以指向派生类对象,这一事实是动态绑定的关键。用引用(或指针)调用的虚函数在运行时
确定,被调用的函数是引用(或指针)所指对象的实际类型所定义的。 
9. 简单描述多重继承中怎样产生的菱形继承问题,又是如何解决的呢? 
最佳答案是:多重继承中爷爷类分别被父亲 1类继承和父亲 2类继承,在父亲 1类和父亲 2类中都有一个
继承来的爷爷类。当子孙类继承自父亲 1类和父亲 2类的时候,子孙类中就产生两个爷爷类。 
解决办法:通过虚继承来解决。 
10. 输出操作符、下标操作符、赋值运算符、自增自减操作符,算术运算符以及关系运算符中哪些操作符
只能用类的成员函数实现,那些只能用类的友元函数实现,哪些即可以用类的成员函数又可以用类的友元
函数实现 
最佳答案是: 
只能用类的成员函数实现:下标操作符、赋值运算符([] () -> =) 
只能用类的友元函数实现:输出操作符 
既可以用类的成员函数实现又可以用类的友元函数实现:自增自减操作符、算术运算符、关系运算符 
11. 简述 map 和 multimap的区别,那 list 和 vector的区别呢 
最佳答案是: 
map 和 multimap:map只能是一对一映射,multimap可以是多对一映射 
list和 vector:list容器顺序访问每个元素,并且从容器前访问元素和容器后访问元素所用时间是一个常数,
vector容器是无序容器,从容器前访问元素花费时间与容器内元素个数成正比,从容器后访问元素花费时
间是一个常数。 
12. 在函数中传引用比传指针安全吗?为什么?如果使用常量指针不行吗? 
最佳答案是:安全,因为引用不申请新的内存空间,而只是另一个变量的别名。常量指针时指向常量的指
针,指针指向的常量无法修改,如果在函数内部想通过指针来修改变量的值是不可以的。 


13. 谈谈你对冒泡排序、选择排序和快速排序的理解 
最佳答案是: 
冒泡排序:通过比较选择出最大的元素放在最后面,缩小范围再次循环选择出倒数第二大的放在倒数第二
个位置,一直到第一个位置。 
选择排序:通过比较选择出最小的元素放在第一个位置,缩小范围再次循环选择出第二小的放在第二个位
置,一直到最后一个位置。 
快速排序:首先选择一个 key,通过一次排序将比 key小的元素都放在左面,将比 key大的元素都放在右
面。然后对 key左面的元素进行递归调用,对 key右面的元素就行递归调用。 
14. 定义一个求两个数中较小值的函数模板,并测试。 
最佳答案是: 
template<class T> 
T min(T a, T b) 

if (a > b) 
return b; 
else 
return a; 

三、编程题
8. 已知 strcpy函数的原型是 
char *strcpy(char *strDest, const char *strSrc); 
其中 strDest是目的字符串,strSrc是源字符串。 
(1)不调用 C++/C的字符串库函数,请编写函数 strcpy 
(2) strcpy能把 strSrc的内容复制到 strDest,为什么还要 char * 类型的返回值? 
最佳答案是:  
char * strcpy(char * strDest,const char * strSrc) 

  char * strDestCopy=strDest; //[3] 
  if((strDest==NULL)||(strSrc==NULL)) //[1] 
    throw "Invalid argument(s)"; //[2] 
  while((*strDest++=*strSrc++)!='\0'); //[4] 
  return strDestCopy; 

返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函
数,如果能合理地提高的可用性,自然就更加理想 
 
原创粉丝点击