本文主要是介绍C++面试常见问题总结(一)(本人面试遇到的问题记录,作为学习和交流用),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
自己大大小小面试了不少企业,做过的笔试题也不少,面对的提问也是各种各样,不过对这些面试总结后还是能发现一些规律(多态,抽象类,设计模式等),由于自己每次面试后都会第一时间记录下面试中的问题,并及时补充遗漏的知识点。这里分几期来将自己面试中遇到的问题列出来并给出自己的理解,作为分享用。愿意交流的可以写下评论。谢谢!
问题1、C与C++有什么区别?
C语言面向过程,C++面向对象。
C语言的内存分配使用的是malloc/free,C++是new/delete。(malloc与new的区别后面讲)
C++是C的超集,所以说C++有C没有的特性,比如继承,封装,多态。以及STL函数库还有多种设计模式,以及可以定义模板。
C++中有类的概念,所以会涉及到构造函数,析构函数,复制构造函数等特性。比较复杂。
C++中的struct具备和类一样的作用和特性,不过struct成员默认访问修饰符是public,class则是private。C中的struct仅仅只是定义了数据块在内存中存储的方式和数据类型。
C++有虚函数概念,重载,覆盖,重写等概念,C没有
C中没有引用的概念,C++有(这点有疑惑)
问题2、C++的特性是什么?有什么作用?
特性是继承,封装和多态。
继承可以扩展已存在的代码模块(类);继承有公有继承,私有继承,保护继承。不同的继承方式规则不同。请见下表
外部指的是对象
封装:封装可以隐藏实现细节,使得代码模块化。通过私有成员变量和函数来实现派生类和其对象无法访问私有成员。
多态作用:接口重用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用, 多态分为编译时多态(重载)和运行时多态(虚函数)。也就是多态分编译时多态和运行时多态,注意的是函数的类型,参数都必须一致,这与重载有不同。
问题3、虚函数原理是什么?如何实现?实用它的场景是什么?举个例子(每次面试比然会考察到的)
虚函数是C++多态的核心,面试必考。解决了运行时多态的问题。基类定义了虚函数后,派生类可以根据此虚函数实现自己的成员函数的实现,也就是实现了覆盖。这样基类指针指向派生类时可以调用派生类的成员函数。
这里也会涉及到多态的概念:
首先多态性有两种,一种是类的多态性,实现的方式是虚函数,以及迟邦定技术(当编译器使用迟绑定时,就会在运行时再去确定对象的类型以及正确的调用函数。而要让编译器采用迟绑定,就要在基类中声明函数时使用virtual关键字)。一种是函数的多态,是指一个函数被定义成多个不同的参数的函数,到底调用哪个函数取决于指针所指的类型。这是在编译器就决定的。
问题4、构造函数特点是什么?里面能否调用虚函数?构造函数调用顺序是什么?
这个问题是当时面试一家外企遇到的笔试题的变形,原题是通过代码来考察此问题。这道题其实还可以有衍生,比如构造函数中能否new本身类等。其实搞清楚基本原理,这些衍生问题都是可以分析出来的。
构造函数其实是在类实例化时对对象进行初始化的作用,可以重载,也可以调用虚函数,但并不实现多态。构造函数不能是虚函数,原因在于:
a、:构造函数是用来建立对象时初始化对象的,在构造函数还没调用完之前是不可能有虚函数表的,那么也就是说函数不可能是虚函数。
b、:虚函数对应一个虚函数表,但是这个虚函数表是存储在对象的内存空间的,那么假如构造函数是虚函数,那么必须通过调用虚函数表来实现,但是这是对象还没实例化,内存空间都没有,所以构造函数是不能为虚函数的。
c、从实现上看,虚函数表在构造函数调用后才建立,因而构造函数不可能为虚函数,从实际含义上看,在调用构造函数时还不能确定对象的真实类型,而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,所以也没有必要成为虚函数。
构造函数调用顺序是先执行基类构造函数,如果基类有虚基类先执行虚基类,其他基类按声明顺序依次执行,在执行成员对象的,最后是自己的。
问题5、写一个STRING类
这个问题是一个很经典的问题,通过手写出此代码,可以考察构造函数,复制构造函数,赋值操作符,,析构函数知识点,深浅拷贝,甚至衍生到单例的懒汉,饿汉模式(后面会讲)。基本上是每次面试中都会有涉及。所以很重要。
Class String {
Public:
String(const char*str=NULL);
~String(){};
String (const String&other);
String &operator=(const String&other); //赋值函数
Private:
Char*m_data;
}
这个String很重要,考察了C++大部分内容,涉及到构造函数的相关知识,赋值函数的知识以及拷贝构造函数的知识。一个例子就可以举一反三,很棒的例子。
构造函数:构造函数可以重载,但构造函数本身不能是虚函数,但是构造函数可以调用虚函数,不过不实现多态。
String::String(const char*str)
{
If(str==NULL)
{
m_data=new char[1];
If(...)//判断是否New成功
{
//.....
}
m_data=’\0’;
}
else
{
int length=strlen(str);
m_data=new char[length+1];
If(...)//判断是否New成功
{
//.....
}
strcpy(m_data,str);
}
}
析构函数:析构函数没有参数和返回值 ,一般来讲析构函数都是虚函数(类中有虚函数时),这样做的好处是避免析构时没有析构派生类而导致内存泄漏。 析构函数不能重载。
String::~String()
{
delete []m_data;
m_data=NULL;
}
拷贝构造函数:拷贝构造函数在三种情况下会调用
- 以值传递的方式作为函数的形参
- 以值传递的方式作为函数的返回值
- 作为另一个同类对象的初始化参数
这里面还涉及到浅拷贝和深拷贝概念
默认拷贝函数是浅拷贝
浅拷贝会出现
深拷贝需要对拷贝构造函数进行修改,添加内存分配的过程,这样才能出现
String ::String(const String &other)
{
int iength=strlen(&other);
m_data=new char[length+1];
If(...)//判断是否New成功
{
//.....
}
strcpy(m_data,other.mdata);
}
复制构造函数出现在将一个对象赋给另一个还没实例化的对象时调用。
赋值函数,赋值函数出现在基于同一个类的对象都已创建,但是需要用其中一个对象赋值给另一个对象时调用赋值函数。
A a;
B b;
B=a;//这时会调用赋值函数
String&String::operator=(const String&other)
{
if(this==other)
{
return this;
}
delete m_data;
m_data=null;
int length=strlen(other.m_data);
m_data=new char[length+1];
If(...)//判断是否New成功
{
//.....
}
strcpy(m_data,other.m_data);
return *this;
}
待续。。。
这篇关于C++面试常见问题总结(一)(本人面试遇到的问题记录,作为学习和交流用)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!