C++11 面试题整理

C++面试题

1 菱形继承

virtual public A

2 多态

多态实现原理:

静态多态
动态多态

静态多态:
依赖函数重载,编译期确定。
函数重载:允许在同一作用于内声明多个功能类似的同名函数,函数列表不同。注意:不能仅通过返回值类型确定重载(函数模板也是其中之一)。

    原理:
    1 函数名修饰;
    2 编译过程:
        预编译 把头文件当中的函数声明拷贝到源文件,避免编译过程中的语法分析找不到函数定义
        * 编译 语法分析,同时进行符号汇总(函数名)
        * 汇编 生成函数名到函数地址的映射,方便通过函数名找到函数定义位置
        链接 将多个文件中的符号表汇总合并

    objdump -t *.o // _Zn + 类长度 + 类名 + 函数名长度 + 函数名 + E + 类型首字母

动态多态:
虚函数重写,运行期确定
在基类的函数名前加virtual关键字,在子类中重写 override
运行时将根据对象的类型调用相应的函数
如果对象的类型是基类,则调用基类函数;反之,若是派生类,则调用派生类函数

使用:
    一般使用基类指针指向对象,如果是基类,指向基类的虚函数表;反之,指向子类的虚函数表

原理:
    早绑定:编译期已确定对象调用的函数地址
    晚绑定:若类使用virtual函数,则会为类生成虚函数表(一维数组,存放虚函数地址),类对象构造时会初始化该虚表指针;
        虚函数表指针在构造时初始化

3 override/final

c++11引入这两个关键字

原因:
虚函数重写
不能阻止某个虚函数进一步重写
本意写一个心函数,错误重写基类虚函数(子类中virtual关键字可省略)
本意重写基类虚函数,但是签名不一致,在子类中重新构建了一个新的虚函数

类继承
    不能阻止某个类进一步派生

override
指定子类一个虚函数复写基类的一个虚函数
保证该重写的虚函数与基类的虚函数具有相同的签名

final
指定某个虚函数不能在派生类中被覆盖,或者某个类不能被派生
阻止类进一步派生
阻止虚函数进一步重写

4 类型推导

类型:
模板方法中模板参数类型的推导
auto decltype (都是c++11引入,其中auto的类型推导是c++引入)

原因:
c++是强类型语言
编译器来处理类型推导
提升语言的编码效率

关键字:
auto
原理:用于推导变量的类型,通过强制声明一个变量的初始值,编译器会通过初始值进行推导类型。
规则:变量必须在定义时初始化;如果用auto定义多个变量,那么这些变量必须为同一类型;类型推导时会丢失cv语义/&;
需要保留&/cv,使用const & / const auto
万能引用 auto&&, 根据初始值的属性来判断左值引用/右值引用
auto不能推导数组类型,会得到指针类型
auto可以推导函数返回值类型(c++14)

    应用:尽量使用auto声明变量,除非影响到可读性
        使用容器时,名字较长,使用auto更方便
        匿名函数返回值
        模板函数中可以节约模板参数类型

    延伸:typeid会丢失顶层const;typeid只有在虚表查找时才会有运行时开销,否则都是在编译阶段完成

decltype
    原理:用于推导表达式的类型,只分析表达式类型而不参与运算
    规则:
        exp是普通表达式,推导表达式类型
        exp是函数调用,推导函数返回值类型
        exp是左值引用,推导出左值引用
    应用:范型编程

5 function/lambda/bind

function
类模板
一个抽象了函数参数以及函数返回值的类模板

    抽象方式:将任意函数包装成一个对象,该对象可以保存/传递/复制;动态绑定,只需要修改该对象(赋值不同的function对象),实现类似多态的效果

用途:保存普通函数,类的静态成员数据;保存仿函数;保存类成员函数;保存lambda表达式
function<void(CHello *, int)> f = &CHello::hello;

仿函数(函数对象)
重载了操作符’()'的类

class Hello {
   
    void operator()(int count) {
   
        i += count;
        cout << "Hello " << i << endl;
    }

    int i;
};
function<void(int)> f = Hello();
f(3);
特征:可以有状态,通过成员变量进行存储;有状态的函数对象成为闭包

lambda表达式
一种方便创建匿名函数对象的语法糖

    int i = 0;
    // auto f_hello = [i]() mutable -> void { ++i; cout << "lambda i:" << i << endl;}; // 未修改外部变量,闭包
    auto f_hello = [&i]() {
    ++i; cout << "lambda i:" << i << endl;}; // 修改外部变量
    f_hello();
    f_hello();

    cout << "global i:" 

你可能感兴趣的:(C/C++,c++)