C++面试知识点总结

目录

1、面向对象(OO)编程的基本原则:SOLID原则 

2、面向对象四大基本特性

3、重载与覆盖的区别

4、谈一下虚函数;

4.1  为什么析构函数是虚函数? 

4.2  而构造函数不能为虚函数? 

5、四种强制转换

6、C++11新特性 

7、C++14新特性:在C++11基础上做了小改动 

8、C++17新特性: 

9、指针和引用: 


面向对象编程思想(OOP) 

1、面向对象(OO)编程的基本原则:SOLID原则 

(1)单一职责原则;S:对象应该仅具有一种单一功能; 

(2)开放封闭原则;O:软件体应该是对于扩展是开放的,对于修改是封闭的; 

(3)Liskov里氏替换原则;L:程序中对象在不改变程序正确性的前提下,被它的子类所替换; 

(4)依赖倒置原则;I:高层次的模块不应该依赖于低层次的模块;抽象接口不应该依赖于具体实现,两者都应该依赖于抽象接口; 

(5)接口隔离原则;D:依赖于抽象而不是一个实例;目的是系统解开耦合,从而容易重构,更改和重新部署。 

2、面向对象四大基本特性

(1)抽象:提取现实世界中某事物的关键特性,为该事物构建建模的过程。 

类与对象体现了C++抽象特性,即类是对象的抽象,对象是类的具体表现形式。 

(2)封装:即隐藏对象的属性和实现细节,仅对外公开接口,控制程序对类属性的读取和修改。 

封装有两方面的含义:一是将有关的数据和操作代码封装在一个对象中,形成一个基本单位,各个对象之间相对独立,互不干扰。二是将对象中某些部分对外隐蔽,即隐蔽其内部细节,只留下少量接口,以便于外界联系,接收外界的消息。 

这种对外界隐蔽的做法称为信息隐蔽。信息隐蔽还有利于数据安全,防止无关的人了解和修改数据。 

(3)继承(重用):类的继承与派生体现了C++的继承特性。 

子类继承父类的特性和行为。 

(4)多态:类的虚函数体现了C++的多态性。 

多态,即同一个行为具有多个不同表现形式或形态的能力。表现形式有覆盖(重写)和重载。 

多态性是指:由继承而产生的不同的派生类,其对象对同一消息做出不同的响应。 

3、重载与覆盖的区别

(1)重载要求函数名相同,但是参数列表必须不同; 

覆盖要求函数名、参数列表、返回值必须相同。 

(2)重载描述的是同一个类中不同成员函数直接的关系; 

覆盖是子类和基类之间不同成员函数之间的关系。 

(3)重载的确定是在编译时确定,是静态; 

虚函数则是在运行时动态确定。 

4、谈一下虚函数;

(1)类的虚函数体现了C++的多态性; 

虚函数如何实现多态:就是用父类的指针指向其子类的对象,父类指针根据赋给它的不同子类指针,动态的调用子类的该函数,而不是父类的函数。 

(2)何为多态性,多态性是指发出的消息被不同的对象接收时会产生完全不同的行为;(同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果) 

(3)实现多态性的方式: 

        a、重载:运算符重载和函数重载; 

        b、静态关联的优缺点:程序执行效率高,但对程序员水平要求较高。  

        c、覆盖:虚函数和纯虚函数。 

        d、动态关联的优缺点:提供更好的编程灵活性、问题抽象性和程序的易维护性,但是函数调用速度慢。 

(4)虚函数是怎么实现多态的:实现原理:虚函数表+虚表指针vptr; 

        a、记住:通过对象调用虚函数不会出现多态(通过指针或者引用才会有多态性) 

        b、编译器处理:为每个类对象添加一个成员vptr,在内存前面; 

        c、虚表属于类,不属于对象;每个类使用一个虚函数表,每个类对象用一个虚表指针。 

        d、空类,内存为1,会有默认的构造和析构函数, 有虚函数的类,内存为4(32),8(64); 

(5)虚析构函数,构造函数不能声明为虚函数。 

(6)纯虚函数与抽象类:包含纯虚函数的类称为抽象类; 

纯虚函数的作用是在基类中为派生类保留一个函数的名字,以便派生类根据需要对它进行定义。 

(7)为什么引入抽象基类和纯虚函数: 

a、为了方便使用多态性 

b、在很多情况下,基类本身生成对象是不合理的。 

(8)虚函数与纯虚函数的区别: 

        a、虚函数是实现的,哪怕是空实现;纯虚函数只是一个接口,是函数声明,需要子类去实现

        b、虚函数在子类中也可以不修改,但纯虚函数必须在子类中实现 

        c、虚函数的类用于“实作继承”,也就是说继承接口的同时也继承了父类的实现,当然也可以完成自己的实现;纯虚函数的类用于“介面继承”,即纯虚函数关注的是接口统一性,现由子类完成。 

        d、带纯虚函数的类叫虚基类(抽象类),这种类不能直接实例化对象,只有被继承,并实现其纯虚函数后,才能使用。 

4.1  为什么析构函数是虚函数? 

我们知道删除指针对象是没有问题的,指针对象的析构函数会正确调用,但仅限于指针的类型所表示的对象大小。 

如果以一个基类指针指向其派生类,删除这个基类指针只能删除基类对象部分,而不能删除整个派生类对象,原因是通过基类指针无法访问派生类的析构函数。 

4.2  而构造函数不能为虚函数? 

原因是构造自己时,对象还不存在。虚函数需要有虚函数表,但这个表因为在构造阶段是不存在的,至少还没分配内存,无法实现定义要求。

5、四种强制转换

(1)static_cast:静态转换,基本数据类型间、有类型指针与void*,基类和派生类、指针与引用; 

(2)dynamic_cast:动态转换,专门用于将多态基类的指针货引用强制转换为派生类的指针或引用;运行时类型检查,不安全会返回null。下行转换,是安全的; 

(3)const_cast:常量转换,仅用于进行去除 const 属性的转换;不能在不同的种类间转换。 

   里面的类型,必须是指针、引用或者指向对象类型成员的指针,不能是对象或者基本类型。 

(4)reinterpret_cast:强转,不安全也不建议。 \

6、C++11新特性 

(1)lambda:[捕获列表](参数列表)mutable修饰符->返回类型{函数体} 

(2)左右值引用: 

       a、左值引用&:对左值进行引用的类型,=右边的值必须可以取地址;int &b = a; 

        b、右值引用&&:=右边需要时右值,可以用std::move强制把左值转换为右值;int &&b = 5;  或者 int &&b = std::move(a); 

(3)移动语义:std::move,转移资源所有权,转为自己所有,别人不再使用。深浅拷贝,直接把原来需要拷贝的内存易主。 

(4)完美转发:std::forward,可以写一个接受任意实参的函数模板,并转发到其他函数,目标函数也会收到与转发函数完全相同的实参;即是:转发函数实参是左值,那目标函数实参也是左值(右值同理)。 

(5)std::function:实现函数回调; 

(6)std::bind:将可调用的对象和参数一起绑定,绑定的结果使用std::function进行保存,并延迟调用到任何我们需要的时候. 

(7)auto:通过=右边的类型推导出变量的类型; 

        decltype:用于推导表达式类型; 

(8)智能指针: 

        a、shared_ptr:多个shared_ptr智能指针可以共同使用同一块内存。(计数机制,add+1,sub-1,引用计数为0,堆内存自动释放); 

        可解决资源忘记释放内存泄露问题,及悬空指针问题。 

        b、unique_ptr:对象对其有唯一所有权.同一个时间只能有一个智能指针可以指向该对象。 

        c、weak_ptr:弱引用,配合shared_ptr使用,指向shared_ptr所管理的对象,但是不会增加引用计数,用于避免循环引用。 

        但是解决相互引用的同时,引用数永远不会为0,所以才用弱引用,不会增加引用计数。 

7、C++14新特性:在C++11基础上做了小改动 

(1)定义变量模板: 

(2)lambda表达式的改动:auto func = [x = 3](auto y) {return x + y; }; 

a、支持lambda泛型参数: 

b、支持初始化捕获: 

(3)constexpr限制放宽: 

8、C++17新特性: 

(1)对auto表达式推导的规则进行了改变: 

(2)lambda表达式可以捕获”*this“,之前捕获this是只读的引用,x在捕获当前对象的拷贝。 

(3)inline变量; 

(4)namespace嵌套; 

9、指针和引用: 

(1)定义和性质不同: 

指针式一个变量,存储的是一个地址,指向内存的一个存储单元; 

引用是原变量的一个别名,和原变量实质上是同一个东西。 

(2)指针可以 有多级,引用只能是一级; 

(3)指针可以在定义时候不初始化,引用必须在定义时候初始化; 

(4)指针可以指向NULL,引用却不可以; 

(5)指针初始化后可以再改变,引用却不可以; 

(6)sizeof的运算结果不同; 

(7)自增运算意义不同: 

指针:指针指向当前指向内存的后面的内存; 

引用:相当于引用原变量的自增; 

(8)指针和引用作为函数参数时,指针需要检查是否为空,引用不需要; 

(9)指针和引用都可以作为函数参数,改变实参的值。 

<think>好的,我需要总结用户关于C++面试常见知识点的需求。用户提供了三个引用来源,看起来都是关于C++面试题和知识点的资料。首先,我应该从这些引用中提取关键点,整理成结构化的内容。 首先,用户提到的引用[1]和[2]中提到了很多基础概念,比如static关键字、四种cast转换、指针和引用的区别、智能指针、虚函数、析构函数、const的使用等。这些都是C++面试中的常见问题。引用[3]则涉及到了引用和指针的区别,以及三目运算符的例子。我需要把这些内容分门别类,确保覆盖主要知识点。 接下来,用户希望知识点总结结构清晰,帮助解决问题。因此,我需要将内容分成几个主要部分,比如基础知识、面向对象、内存管理、标准库等。每个部分下列举具体的问题和简要解答,同时注意使用中文,并且按照系统指令正确使用LaTeX格式。 要注意用户提到的系统级指令,比如行内数学表达式用$...$,独立公式用$$...$$。不过在当前的回答中,可能涉及代码块较多,数学公式较少,但如果有的话需要正确应用。例如,在解释某些算法或内存地址计算时可能需要数学表达式。 另外,用户要求生成相关问题,放在最后。这些问题需要围绕C++面试知识点展开,覆盖不同部分的内容,帮助用户进一步复习。 需要确保LaTeX语法正确,例如代码中的变量或表达式使用$符号包裹。同时,回答中的引用标识要自然添加,但用户提供的引用内容可能没有直接对应的文献,所以可能需要根据现有引用内容适当标注,比如引用[^1]、[^2]、[^3]。 最后,检查是否有遗漏的重要知识点,比如多态、虚函数表、智能指针的实现、STL容器区别等,确保覆盖用户提供的引用中的内容,并按照逻辑组织,便于用户理解和复习。</think>以下是对C++面试常见知识点的结构化总结,结合基础语法、面向对象、内存管理等核心领域: --- ### 一、基础语法与关键字 1. **`static`关键字** - 修饰局部变量:延长生命周期至程序结束 - 修饰全局变量/函数:限制作用域为当前文件 - 修饰类成员:属于类而非对象,可通过类名直接访问[^1] 2. **`const`关键字** - 修饰变量:声明常量,如`const int MAX=100;` - 修饰成员函数:禁止修改对象成员,如`void func() const;` - 与指针结合:`const int* p`(指针可变,值不可变) vs `int* const p`(指针不可变,值可变)[^3] 3. **四种类型转换** - `static_cast`:基本类型转换(如`int`转`double`) - `dynamic_cast`:用于多态类型安全向下转型 - `const_cast`:移除`const`属性 - `reinterpret_cast`:低级别强制转换(如指针转整数)[^1] --- ### 二、面向对象特性 1. **虚函数与多态** - 虚函数表(vtable)实现运行时多态 - 纯虚函数定义接口:`virtual void func() = 0;` - **析构函数必须为虚函数**:确保派生类对象正确释放[^2] 2. **访问权限与继承** - `public`继承:基类成员权限不变 - `protected`继承:基类`public`成员变为`protected` - `private`继承:基类所有成员变为`private`[^1] 3. **重载、覆盖与隐藏** - 重载(Overload):同名函数参数不同 - 覆盖(Override):派生类重写基类虚函数 - 隐藏(Hide):派生类函数屏蔽基类同名函数[^2] --- ### 三、内存管理 1. **智能指针** - `unique_ptr`:独占所有权,不可拷贝 - `shared_ptr`:引用计数共享所有权 - `weak_ptr`:解决`shared_ptr`循环引用问题[^2] 2. **`new/delete` vs `malloc/free`** - `new`调用构造函数,`malloc`仅分配内存 - `delete`调用析构函数,`free`直接释放内存 ```cpp int* p1 = new int(5); // 分配并初始化 int* p2 = (int*)malloc(sizeof(int)); // 仅分配 ``` 3. **内存泄漏与野指针** - 内存泄漏:未释放已分配内存(如忘记`delete`) - 野指针:指向无效内存的指针(如释放后未置空)[^2] --- ### 四、标准库与容器 1. **STL容器对比** | 容器 | 特点 | 时间复杂度(插入/查找) | |---------------|------------------------|-------------------------| | `vector` | 动态数组,随机访问快 | 尾部插入$O(1)$ | | `list` | 双向链表,插入删除快 | 任意位置插入$O(1)$ | | `map` | 红黑树实现,有序 | 查找$O(\log n)$ | | `unordered_map`| 哈希表实现,无序 | 查找平均$O(1)$ |[^2] 2. **迭代器与指针** - 迭代器提供统一访问接口,支持泛型编程 - 指针是原生类型,迭代器可能封装更复杂逻辑(如`map`的树遍历)[^2] --- ### 五、其他高频考点 1. **函数返回值处理** - 临时变量通过寄存器或栈传递,可能触发拷贝构造函数[^1] 2. **`volatile`关键字** - 禁止编译器优化,确保每次从内存读取变量(常用于多线程或硬件编程)[^1] 3. **位运算技巧** - 判断是否为2的倍数:`(n & (n-1)) == 0` - 统计二进制中1的个数:循环执行`n &= n-1`直到为0[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值