zoukankan      html  css  js  c++  java
  • 面试题总结

    1.int f(int a)能重载void f(int a)吗?重载是在编译期还是运行期?

    答:不能重载,因为调用时不能指定类型信息,编译器不知道你要调用哪个函数。 重载是在编译器,虚函数多态(重写)才是在运行期。

    2.拷贝构造函数作用及用途?什么时候需要自定义拷贝构造函数?

    答:(1)在C++中,有下面三种对象需要拷贝的情况:

    a.一个对象以值传递的方式传入函数体

    b.一个对象以值传递的方式从函数返回

    c.一个对象需要通过另一个对象进行初始化

    以上的情况就需要拷贝构造函数的调用

    (2)当类中数据成员需要动态分配存储空间时,不可以依赖default copy constructor 。当default copy constructor被编译器需要而和成时,将执行default memberwise copy 语义。

    此时如果类中有动态分配的存储空间时,将会发生惨重的灾情。

    3.构造函数可以调用虚函数吗?

    答:不能,语法上通过,语义上有问题。 
    derived class对象内的base class成分会在derived class自身构造之前构造完毕。因此,在base class的构造函数中执行的virtual函数将会是base class的版本,决不会是derived class的版本。 
    即使目前确实正在构造derived class。

    4.c++11 有哪些改进?有哪些东西 ?

    答: lambda 线程库  智能指针 auto

    5.如果实现一个不能在对上分配的类?如果实现一个不能被继承的类?

    答:在堆上分配就需要用到new操作符,重载new操作符并将其放于private内。  这个用到C++ 11新关键字final

    class B final {
    public:
        B(int a) {
        }
    };
    

      现在就不能继承了

    6.引用和指针右什么区别?

    答:

    (1)定义一个指针变量编译器会为它分配内存,而引用不占用任何内存;

    (2)引用必须在定义时被初始化,指针不必;

    (3)不存在指向空值的引用,但存在指向空值的指针。

    7.函数参数传递中值传递、地址传递、引用传递有什么区别?

    答:

    (1) 值传递,会为形参重新分配内存空间,将实参的值拷贝给形参,形参的值不会影响实参的值,函数调用结束后形参被释放;

    (2) 引用传递,不会为形参重新分配内存空间,形参只是实参的别名,形参的改变会影响实参的值,函数调用结束后形参不会被释放;

    (3) 地址传递,形参为指针变量,将实参的地址传递给函数,可以在函数中改变实参的值,调用时为形参指针变量分配内存,结束时释放指针变量。

    8.static关键字有什么作用?

    答:

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

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

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

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

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

    9.const关键字有什么作用?

    答:

    (1)阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它初始化,因为以后就没机会改变它了;

    (2)对指针来说,可以指定指针本身为const,也可指定指针所指的数据为const,或二者同时指定为const;

    (3) 在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;

    (4) 对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;

    (5) 对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为左值。

    10 .链表和数组的区别在哪里?

    (1) 链表和数组都可以叫线性表,数组又叫顺序表,主要区别在于,顺序表是在内存中开辟一段连续的空间来存储数据,而链表是靠指针来连接多块不连续的空间,在逻辑上形成一片连续的空间来存储数据;

    (2) 数组要求空间连续,占用总空间小,链表不要求空间连续,占用总空间大;

    (3) 数组方便排序和查找,但删除和插入较慢;链表方便删除和插入,但查找较慢,不方便排序。

    11.进程和线程的差别?

    答:

    线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别:

    (1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位;

    (2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程也可以并发执行;

    (3)拥有资源:进程是拥有资源的一个独立单元,线程不拥有系统资源但可以访问隶属于进程的资源;

    (4)系统开销:在创建或撤销进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤销线程时的开销。

    12.C++重写、重载、重定义的区别?

    (1)成员函数重载特征:

    a.相同的范围,在同一个类

    b.函数名字相同

    c.参数不同

    (2)重写(覆盖)是指派生类函数覆盖基类函数,特征是:

    a.不同的范围,分别位于基类和派生类中

    b.函数的名字相同

    c.参数相同

    d.基类函数必须有virtual关键字

    (3)重定义(隐藏)是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

    a.如果派生类的函数和基类的函数同名,但是参数不同,此时不管有无virtual,基类的函数被隐藏;

    b.如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字,此时基类函数被隐藏。

    13.一个数据成员是否可以既是const又是static,如果不行,为什么?

    (1)一个数据成员可以既是const又是static,表示为静态常量;

    (2)常量一般在构造函数后初始化;

    (3)静态成员一般在类外初始化;

    (4)静态常量在类外初始化,但要在类外初始化的同时声明为const。

    14.构造函数与析构函数的异同点?

    答:

    1.构造函数有如下特点:

    (1)构造函数的名字必须与类名相同;

    (2)构造函数可以有任意类型的参数,但不能有返回类型;

    (3)定义对象时,编译系统会自动调用构造函数;

    (4)构造函数是特殊的成员函数,函数体可以在类体内也可以在类体外;

    (5)构造函数被声明为公有函数,但它不能像其他成员函数那样被显式调用,它是在定义对象的同时被调用的。

    2.析构函数有如下特点:

    (1)析构函数的名字必须与类名相同,但它前面必须加一个波浪号;

    (2)析构函数没有参数,也没有返回值,而且不能被重载,因此在一个类中只能有一个析构函数;

    (3)当撤销对象时,编译系统会自动调用析构函数;

    (4)析构函数可以是virtual,而构造函数不能是虚函数。

    15.简述C++异常处理方式?

    答:

    一个典型的C++异常处理包含以下几个步骤:

    (1)程序执行时发生错误;

    (2)以一个异常对象(最简单是一个整数)记录错误的原因及相关信息;

    (3)程序监测到这个错误(读取异常对象);

    (4)程序决定如何处理错误;

    (5)进行错误处理,并在此后恢复/终止程序的执行。

    16.成员函数和友元函数的区别?

    (1)成员函数是类定义的一部分,通过特定的对象来调用。成员函数既可以隐式访问调用对象的成员,而无须使用成员操作符;

    (2)友元函数不是类的组成部分,因此被称为直接函数调用。友元函数不能隐式访问类成员,而必须将成员操作符用于作为参数传递的对象。

    17.函数模板与函数重载的异同?

    (1)函数的重载是指定义了几个名字相同,但参数的类型或参数的个数不同的函数;

    (2)模板函数是指的几个函数的具体算法相同,而参数类型不同的函数;

    (3)模板函数可以减少重载函数,但也可能引发错误。

    18.面向对象的三大特征是什么?

    面向对象的三个基本特征:封装、继承、多态。

    19.什么是封装?

    (1)封装是面向对象的特征之一,是对象和类概念的主要特性;

    (2)封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏;

    (3)在C++中类中成员的属性有:public、protected、private,这三个属性的访问权限依次降低。

    20.什么是继承?

    (1)继承是指:可以使用现有类的所有功能,并在无须重新编写原来的类的情况下对这些功能进行扩展;

    (2)通过继承创建的类称为“子类”或“派生类”;

    (3)被继承的类称为“基类”、“父类”或“超类”;

    (4)在某些OOP语言中,一个子类可以继承多个基类,但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现;

    (5)C++中可以用public、protected、private来修饰继承特性。

    21.什么是多态?

    (1)多态性:允许将父类对象设置为和一个或更多的它的子对象相等的技术,赋值之后,父对象可以根据当前赋值给它的子对象的特性以不同的方式运作。简单地说,允许将子类类型的指针赋值给父类型的指针;

    (2)实现多态的两种方式:覆盖、重载;

    (3)覆盖:子类重新定义父类的虚函数;

    (4)重载:允许存在多个同名函数,而这些函数的参数表不同。

    22.不可以同时用const和static修饰成员函数。

    C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时const的用法和static是冲突的。我们也可以这样理解:两者的语意是矛盾的。static的作用是表示该函数只作用在类型的静态变量上,与类的实例没有关系;而const的作用是确保函数不能修改类的实例的状态,与类型的静态变量没有关系。因此不能同时用它们。

    23.类型安全以及C++中的类型转换?

    四种类型转换:

    • static_cast <T*> (content)  静态转换.在编译期间处理,可以实现C++中内置基本数据类型之间的相互转换。如果涉及到类的话,static_cast只能在有相互联系的类型中进行相互转换,不一定包含虚函数。
    • dynamic_cast<T*>(content) 动态类型转换;也是向下安全转型;是在运行的时候执行;基类中一定要有虚函数,否则编译不通过。在类层次间进行上行转换时(如派生类指针转为基类指针),dynamic_cast和static_cast的效果是一样的。在进行下行转换时(如基类指针转为派生类指针),dynamic_cast具有类型检查的功能,比static_cast更安全。
    • const_cast<T*>(content) 去常转换;编译时执行;
    • reinterpret_cast<T*>(content) 重解释类型转换;

    24 C语言和C++有什么区别? 
        C语言是结构化的编程语言,它是面向过程的,而C++是面向对象的。 
        封装:将数据和函数等集合在一个单元中(即类)。被封装的类通常称为抽象数据类型。封装的意义在于保护或者防止代码(数据)被我们无意中破坏。 
        继承:继承主要实现重用代码,节省开发时间。它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 
        多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向派生类的基类指针,来调用实现派生类中的方法。有编译时多态和运行时多态。

    25.如何实现类对象只能静态分配或动态分配?

    C++中建立类的对象有两种方式:
    (1)静态建立,例如 A a;
         静态建立一个类对象,就是由编译器为对象在栈空间中分配内存。使用这种方法,是直接调用类的构造函数。
    (2)动态建立,例如 A* p = new A();
         动态建立一个类对象,就是使用new运算符为对象在堆空间中分配内存。这个过程分为两步:第一步执行operator new( )函数,在堆空间中搜索一块内存并进行分配;第二步调用类的构造函数构造对象。这种方法是间接调用类的构造函数。

    只能动态分配:  

          其实,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性(其实不光是析构函数,只要是非静态的函数,编译器都会进行检查)。如果类的析构函数在类外部无法访问,则编译器拒绝在栈空间上为类对象分配内存。因此,可以将析构函数设为private,这样就无法在栈上建立类对象了。但是为了子类可以继承,最好设置成protected。
    class A  
    {  
    protected:  
         A(){}  
         ~A(){}  
    public:  
         static A* create(){return new A();}  
         void destory(){delete this;}  
    };  
    

      

    只能静态分配:

        只有使用new运算符,对象才会被建立在堆上。因此只要限制new运算符就可以实现类对象只能建立在栈上。可以将new运算符设为私有。

    class A  
    {  
    private:  
         void* operator new(size_t t){}            //注意函数的第一个参数和返回值都是固定的  
         void  operator delete(void* ptr)()        //重载了new就需要重载delete  
    public:  
         A(){}  
         ~A(){}  
    };  
    

    26auto_ptr类与shared_ptr类?

    从c++11开始, auto_ptr已经被标记为弃用, 常见的替代品为shared_ptr。shared_ptr的不同之处在于引用计数, 在复制(或赋值)时不会像auto_ptr那样直接转移所有权。 两者都是模板类,却可以像指针一样去使用。只是在指针上面的一层封装。

          auto_ptr实际也是一种类, 拥有自己的析构函数, 生命周期结束时能自动释放资源,正因为能自动释放资源, 特别适合在单个函数内代替new/delete的调用, 不用自己调用delete,也不用担心意外退出造成内存的泄漏。

       atuo_ptr的缺陷:

    •  auto_ptr不能共享所有权,即不要让两个auto_ptr指向同一个对象(因为它采用的是转移语义的拷贝,原指针会变为NULL)。
    •  auto_ptr不能管理对象数组(因为它内部的析构函数调用的是delete而不是delete[])。
    •  auto_ptr不能作为容器对象,STL容器中的元素经常要支持拷贝,赋值等操作,在这过程中auto_ptr会传递所有权。
    • shared_ptr 使用引用计数的方式来实现对指针资源的管理。同一个指针资源,可以被多个 shared_ptr 对象所拥有,直到最后一个 shared_ptr 对象析构时才释放所管理的对象资源。

            可以说,shared_ptr 是最智能的智能指针,因为其特点最接近原始的指针。不仅能够自由的赋值和拷贝,而且可以安全的用在标准容器中。

    27. C++是不是类型安全的?

    答:不是,两个不同类型的指针之间可以可以强制转换(reinterpret cast)

  • 相关阅读:
    Linux中使用 FTP 命令时出现 “-bash: ftp: command not found”
    Jenkins Build step 'Execute shell' marked build as failure
    centos7ping www.baidu.com没有ping通
    linux maven 安装
    位运算初步
    C++ STL:next_permutation和prev_permutation
    逆波兰表达式
    STL与基本数据结构
    学习记录:指针(未整理)
    Codeforces Round #615 (Div. 3) 补题记录
  • 原文地址:https://www.cnblogs.com/wuyepeng/p/9609645.html
Copyright © 2011-2022 走看看