C++面试常见问题总结(一)(本人面试遇到的问题记录,作为学习和交流用)

本文主要是介绍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;

         }

拷贝构造函数:拷贝构造函数在三种情况下会调用

  1. 以值传递的方式作为函数的形参
  2. 以值传递的方式作为函数的返回值
  3. 作为另一个同类对象的初始化参数

这里面还涉及到浅拷贝和深拷贝概念

    默认拷贝函数是浅拷贝

   浅拷贝会出现

深拷贝需要对拷贝构造函数进行修改,添加内存分配的过程,这样才能出现

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++面试常见问题总结(一)(本人面试遇到的问题记录,作为学习和交流用)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1007449

相关文章

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

在Spring Boot中集成RabbitMQ的实战记录

《在SpringBoot中集成RabbitMQ的实战记录》本文介绍SpringBoot集成RabbitMQ的步骤,涵盖配置连接、消息发送与接收,并对比两种定义Exchange与队列的方式:手动声明(... 目录前言准备工作1. 安装 RabbitMQ2. 消息发送者(Producer)配置1. 创建 Spr

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

解析C++11 static_assert及与Boost库的关联从入门到精通

《解析C++11static_assert及与Boost库的关联从入门到精通》static_assert是C++中强大的编译时验证工具,它能够在编译阶段拦截不符合预期的类型或值,增强代码的健壮性,通... 目录一、背景知识:传统断言方法的局限性1.1 assert宏1.2 #error指令1.3 第三方解决