1.什么是虚函数?什么是纯虚函数?
在C++中,虚函数是基类中声明为virtual
的成员函数;当虚函数在基类中没有定义,即只有声明而没有函数体时,它被称为纯虚函数。
2.基类为什么要虚析构函数?
1>正确释放资源
2>多态的正确实现
3>避免内存泄漏
4>遵循RAII原则
3.如何初始化const和static数据成员
const:
1>直接在类定义中初始化
2>在构造函数的初始化列表中初始化
static:
1>对于基本数据类型
2>对于复杂的数据类型
4.指针和引用的区别
- 指针可以重新赋值指向其他地址,引用一旦绑定到一个对象就不能改变。
- 指针可以为空(
nullptr
),引用必须在定义时就被初始化。 - 指针可以进行算术运算,引用不可以。
- 指针需要使用
*
和&
操作符,引用使用起来就像普通变量。 - 指针可以存储在变量中,引用通常不存储在变量中,它们是对象的别名。
- 指针可以返回函数中的动态分配内存,引用通常用于返回函数外部的对象。
5.new和malloc区别
new
是 C++ 中的运算符,而malloc
是 C 语言中的函数。new
除了分配内存外,还会调用对象的构造函数来初始化对象,而malloc
只分配内存,不初始化对象。new
分配的内存是自动管理的,对象可以被自动销毁,而malloc
分配的内存需要手动使用free
函数释放。new
返回的是对象类型的指针,可以直接赋值给对象类型的指针,而malloc
返回的是void*
类型的指针,需要进行类型转换。new
表达式可以抛出异常,而malloc
返回NULL
来表示内存分配失败。new[]
用于分配数组,malloc
需要结合循环来分配数组。new
可以与多态一起使用,malloc
不能用于多态对象的分配。
6.内存泄露怎么产生的?如何避免?
如何产生:
- 动态分配内存未释放:使用
new
或malloc
分配了内存,但未使用delete
或free
释放。 - 野指针:指针未初始化或未指向有效的内存地址,导致无法释放指向的内存。
- 循环引用:对象之间相互引用,导致无法被垃圾回收机制回收。
- 资源未关闭:文件句柄、网络连接、数据库连接等资源未正确关闭。
- 异常处理不当:在抛出异常前未释放已分配的资源。
如何避免:
- 使用智能指针:如
std::unique_ptr
、std::shared_ptr
等,它们可以自动管理内存。 - 确保每次
new
都有对应的delete
:分配和释放内存要成对出现。 - 初始化所有指针:避免使用未初始化的指针。
- 避免循环引用:使用弱引用或适当设计对象的生命周期。
- 资源释放:确保所有资源(如文件、网络连接)在使用完毕后都被正确关闭。
7.C++的内存分区
- 栈区(Stack):自动分配和释放,用于存储函数调用时的局部变量、参数和返回地址。
- 堆区(Heap):动态分配和释放,由程序员控制,通过
new
和delete
进行内存的分配和释放。 - 全局/静态存储区(Global/Static Storage):存储全局变量和静态变量,包括初始化和未初始化的变量。
- 代码区(Code Segment):存储程序的可执行代码和一些只读的常数变量,如字符串常量。
- 常量区(Constant Storage):存储常量数据,通常也是只读的
8.说说您常用的设计模式和应用场景
9.常用的数据结构有哪些?时间复杂度和空间复杂度如何使用?
1>数组,链表,栈,队列,哈希表,二叉树,堆
2>时间复杂度通常描述了算法执行时间与输入规模的关系,而空间复杂度描述了算法执行过程中所需存储空间与输入规模的关系。
10.描述Qt下Tcp通信的整个流程
-
服务器端:
- 创建
QTcpServer
对象用于监听端口。 - 调用
listen()
方法开始监听客户端的连接请求。 - 接收连接请求,通过
newConnection()
信号获取新的QTcpSocket
连接。 - 使用
QTcpSocket
对象进行数据的读写操作。
- 创建
-
客户端:
- 创建
QTcpSocket
对象用于建立连接。 - 调用
connectToHost()
方法连接到服务器。 - 连接成功后,使用
QTcpSocket
对象进行数据的读写操作。
- 创建
11.如何使用c++模拟Qt信号和槽
-
定义信号:使用
std::function
和std::vector
来定义一个可存储多个回调函数的容器,代表信号。 -
连接信号与槽:提供一个连接函数,允许用户将成员函数或自由函数注册到信号的回调列表中。
-
发射信号:定义一个发射函数,遍历回调列表并调用所有注册的回调函数。
-
定义槽:槽可以是成员函数、自由函数或任何可调用对象。
12.Qt中的智能指针
C++11 新特性
|
|-- Lambda 表达式
| |-- 引入原因
| | |-- 函数体内需要定义轻量级函数
| | `-- 提供独立空间实现独立操作
| |-- 定义格式
| | |-- [捕获列表](函数形参)[mutable] [->返回值类型] {函数体内容}
| | |-- 捕获列表
| | | |-- 值捕获
| | | | |-- [=] 全部值捕获
| | | | `-- [变量1, 变量2] 部分值捕获
| | | `-- mutable 关键字
| | | `-- 允许修改值捕获的变量
| | |-- 引用捕获
| | | | |-- [&] 全部引用捕获
| | | | `-- [&变量1, &变量2] 部分引用捕获
| | | `-- 混合捕获
| | | |-- [变量1, &变量2]
| | | `-- [&, 变量1, &变量2]
| | `-- 返回值类型
| | |-- 可指定或自动推导
| | `-- 影响函数返回值
| `-- 示例代码
| |-- 值捕获示例
| `-- 引用捕获示例
|
|-- 异常处理
| |-- 定义
| | |-- 程序执行中无法解决的问题
| | `-- C++ 中的异常处理机制
| |-- 异常处理格式
| | |-- throw 抛出异常
| | `-- try-catch 捕获异常
| |-- 示例代码
| | |-- 抛出字符串异常
| | `-- 抛出 const char* 异常
| `-- noexcept 关键字
| `-- 表示函数不会抛出异常