C++面试最常见问题(一)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

一、指针和引用的区别

答: 1、指针可以指向空,也可以更改指向的对象;而引用的本质是指针常量,指向不可以改,值可以改,引用在使用时不能指向空,必须要初始化,且必须对以初始化对象的引用。 2、指针可以有多级指针,而引用只能有一级。 3、指针有属于自己的空间,即地址;而引用是给变量起别名。 4、sizeof(指针)在16位系统上的大小为2,,在32位系统上是4,在64位系统上是8;而引用则是引用对象的大小。 5、做参数时,指针需要解引用才能对对象进行操作;而对引用进行修改会直接改变引用所指向的对象。

二、谈谈你对面向过程和面向对象的理解

答: 面向过程:将解决问题的步骤分析出来,用函数实现,进而一步步调用。(就相当于一件事的流程,首先要干什么,其次干什么,最后干什么) 面向对象:是将现实问题构建关系,然后抽象成类,给类定义属性和方法后,再将类实例化为具体的对象 ,通过访问实例化对象的属性和行为来进行调用。 举个简单的例子:做一个象棋游戏小程序 制作一个象棋程序,使用面向过程的设计思路就是首先分析问题的步骤:1、开始游戏,2、红旗先走,3、绘制画面,4、判断输赢,5、轮到黑旗,6、绘制画面,7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就解决了。 而面向对象的设计则是从另外的思路来解决问题。整个象棋可以分为 1、黑红双方,这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、输赢等。 第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局的变化,棋盘对象接收到了棋子的变化就要负责在屏幕上面显示出这种变化,同时利用第三类对象(规则系统)来对棋局进行判定。 可以明显地看出,面向对象是以功能来划分问题,面向过程是按步骤来解决问题。同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能在棋盘对象中出现,从而保证了绘图的统一。功能上的统一保证了面向对象设计的可扩展性。比如我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要改动,甚至步骤之间的循序都要进行大规模调整。而面向对象的话,只用改动棋盘对象就行了,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个对对象功能的调用顺序都没有变化,改动只是局部的。

三、C++三大特性

答: 1、封装 封装就是将一类事物的属性和行为抽象成一个类,使其属性私有化,行为公开化,提高了数据的隐秘性的同时,使代码模块化。这样做使得代码的复用性更高。 2、继承 继承则是进一步将一类事物共有的属性和行为抽象成一个父类,而每一个子类继承父类,有父类的行为和属性,也有自己特有的行为和属性。这样做扩展了已存在的代码块,进一步提高了代码的复用性。 3、多态 多态分为静态多态和动态多态。静态多态是重载,动态多态是重写。多态的作用就是实现接口重用。允许父类指针或引用(或接口)指向子类(或实现类)对象。

四、动态多态的实现过程

答: 1、由于使用了虚函数,类的内部结构发生了改变,多了一个虚函数指针,虚函数指针指向虚函数表(虚函数表存放虚函数的入口地址); 2、当子类重写了父类的虚函数,子类的虚函数表中的地址替换成了子类的虚函数地址; 3、当父类指针或引用指向子类对象时,由于本身还是还是子类对象,从子类走入口地址。 总结: 多条满足条件: (1)有继承关系(2)子类重写父类虚函数 多态使用条件: 父类指针或引用指向子类对象

五、为什么要引入纯虚函数

答: 1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。 2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。 3、基类中实现的函数没用到或者没有意义。   为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。 当类中有了纯虚函数,这个类也就成为抽象类,抽象类的特点: 1.无法实例化对象 2.子类必须重写抽象类中的纯虚函数,不然也属于抽象类

六、为什么引入虚析构和纯虚析构,他们有什么区别

答: 多态使用时,如果子类有属性开辟到堆区,那么父类指针在释放时无法调用子类的析构代码 解决方法: 将父类的析构函数改为虚析构或者纯虚析构 虚析构和纯虚析构共同点和区别: 共同点: 1.可以解决解决父类指针释放子类对象 2.需要有具体的函数实现。 区别:如果是纯虚析构,该类属于抽象类,无法实例化对象。

七、C和C++的区别

答: 1、c是面向过程的编程,c++是面向对象的过程。 2、动态管理内存的方式不同,c中是malloc/free,c++中是new/delete。 3、c++中有类class,c中是struct等同于类的使用。 4、c++支持重载,c中不支持重载。 5、c++中有引用,c中没有。 6、c++中变量默认外连接,c中默认内连接。 7、c中const'修饰的变量不可以用在定义数组的大小,c++中可以。 8、c++中有特定的输入输出流。

八、malloc/free和new/delete的区别

答: 1、malloc/free为C的标准库函数,它的调用方式分别为 void* malloc(size_t size),void free(void* pointer);new/delete则为C++的操作运算符,它调用的分别为赋值运算符重载operator new()和operator delete();都可用于申请动态内存和释放内存。 2、由于malloc/free不是运算符,所以其不在编译器的编译范围内,所以不能进行构造/析构,因此需要完成动态内存分配和初始化的运算符new和清理释放内存的运算符delete。 3、new=malloc+构造。new出的指针带类型信息,malloc返回void*,必须强制类型转换对应类型指针。 4、malloc从堆上开辟空间,new从自由存储区开辟空间(堆、静态存储区)。 5、malloc开辟的空间小,换更大的空间可以用relloc;new没有直观改变的方法。 6、malloc开辟内存时返回内存地址要检查判空,因为若它可能开辟失败会返回NULL;new则不用判断,因为内存分配失败时,它会抛出异常bac_alloc,可以使用异常机制。 7、new/delete是操作符,它们可以被重载,在标准库里它有8个重载版本;而malloc/free不可以重载; 8、new/delete底层是基于malloc/free来实现的,而malloc/free不能基于new/delete实现;

九、C++中参数有几种传递方式,他们之间有什么区别。

答: 有三种传递方式,分别为值传递、指针传递、引用传递。 1、值传递,会为形参重新分配内存空间,将实参的值拷贝给形参,形参的值不会影响实参的值,函数调用结束后形参被释放; 2、指针传递,形参为指针变量,将实参的地址传递给函数,可以在函数中改变实参的值,调用时为形参指针变量分配内存,结束时释放指针变量。 3、 引用传递,不会为形参重新分配内存空间,形参只是实参的别名,形参的改变会影响实参的值,函数调用结束后形参不会被释放;

十、为什么引入深拷贝,深拷贝与浅拷贝的区别。

答: 引入深拷贝是为了解决堆区内存重复释放的问题, 深浅拷贝的区别: 浅拷贝是简单的赋值拷贝工作。深拷贝是在堆区重新申请空间,进行拷贝工作。当对象中没有其他的资源(如:堆,文件,系统资源等),则深拷贝和浅拷贝没有什么区别。

总结

本人也处于学习阶段,也是在学习的过程中经常碰到这些问题,文中难免有总结的不到位的地方,大家多多包涵,欢迎大家一起学习交流讨论(* ̄︶ ̄)。

猜你喜欢

转载自blog.csdn.net/qq_46901210/article/details/124167103