+++
author = "Wxn"
title = "2024-04-19面试复盘"
date = "2024-04-19"
description = "Please read me first."
tags = [
"Dilay",
]
categories = [
"面试复盘",
]
+++
This article offers a sample of basic Markdown.
# 正文开始
在线编程工具:
https://www.bejson.com/runcode/c740/
sizeof(空类) = 1;
静态成员变量和成员函数都不占类的大小(sizeof),也就是说静态成员变量和成员函数都不属于类
```
继承下面说了
封装:将变量设置为protected或者provate,限制这些变量在类外的直接访问,我们可以使用get常量函数来完成对这个变量的封装
protected:当一个成员被定义为protected类型时,仅能在类内、友元和派类访问。
private:当一个成员被定义为private类型时,仅能在类内、友元访问。
多态下面说了
```
## 1.struct和class的区别
首先,class是cpp独有的,c语言里面没有,
然后就是在cpp中,class的默认访问权限是private,而struct是public;
还有就是class默认都是私有继承,而sruct默认是公有继承.
最后一点是,在语法上的区别,你使用cpp中 ,
不管是struct还是class,都可以直接使用类名.
在c语言中,要么写 struct A a;(带上struct),要么你用typedef struct A A;一下
涉及知识:https://blog.csdn.net/weixin_52668597/article/details/136666085?spm=1001.2014.3001.5501
补充:公有继承,保护继承与私有继承下,类内的元素的权限变化:
- 公有继承:原来啥权限就还是啥权限,一点不变
- 保护继承:原来公有变保护,其他两个->原来啥权限就还是啥权限
- 私有继承:原来公有变私有,原来保护变私有,原来私有还是私有
## 2.值传递,地址传递,引用传递(拷贝)的区别
值传递你无法在函数中改变这个变量的值
地址传递和引用你可以在函数中改变这个变量的值
值传递相当于是你建立了一个副本,你是你,他是他,你的改变无法影响到他,他的改变无法影响到你.
地址传递的话,传进去的就是本人了,此时修改地址上的数据会影响到原始数据.
而引用传递相当于是给该变量取的别名,相当于是一个大名一个小名比如鲁迅和周树人,本质上还是一个人,所以改变引用传递的变量也可以改变变量的原始数据
## 4.指针是几个字节?
64位系统是8字节
32位系统是4字节
## 5.static关键字
static的用法分为静态变量与静态函数
静态变量将变量限定在当前文件下,且生命周期和该文件运行的周期一样长.
然后再细分就是局部静态变量与全局静态变量:局部静态变量被限定在一个代码块内(一般是一个函数),而全局静态变量只要是在这个文件内,都可以访问.
再者就是静态函数了,静态成员函数只能访问静态成员变量
然后就是,类中的静态成员变量并不属于这个类,你用sizeof去算,他不算这个类的大小
涉及知识:cpp编译单元 https://blog.csdn.net/weixin_52668597/article/details/137575061?spm=1001.2014.3001.5501
## 6.虚函数指针,虚函数表
涉及知识:https://blog.csdn.net/weixin_52668597/article/details/137447982?spm=1001.2014.3001.5501
只要你在类中写了一个虚函数,那么就会产生一个虚函数表.
而且不管你写多少个虚函数,这些虚函数在类中所占的内存就只有8个字节,而占的这八个字节就是虚函数指针,也就是说,这些虚函数都放在一个数组中,这个数组就是虚函数表
## 7.多态
涉及知识:https://blog.csdn.net/weixin_52668597/article/details/137447982?spm=1001.2014.3001.5501
多态其实就是 父类指针指向子类对象,如果子类重写了父类的方法,那么这个父类指针就会呈现出不同的现象
## 8.编译器如何知道你是进行的函数重载
答:函数重载,它允许在同一个作用域中定义多个同名函数,但这些函数的参数列表或类型必须不同。在调用这些函数时,编译器会根据传递给函数的参数的数量、类型或顺序来确定要调用的具体函数版本。
简单来讲,就是函数重载可以是参数类型不同,参数顺序不同,也可以是参数个数不同
编译器会在内部,把函数名称和参数列表一起存储在符号表中,这样编译器就知道了你用的是哪个重载之后的函数
就是,编译器在处理函数重载时,会将函数名称和参数列表一起存储在符号表(或类似符号表的数据结构)中。这样编译器就能够确定每个函数的唯一签名,并且在需要进行函数调用匹配时可以快速检索并确定调用哪个函数版本。
## 9.构造,析构的顺序
在C++中,对象的构造和析构顺序
最主要是
和对象的创建和销毁顺序相关。
一般情况下,对象的构造顺序与对象的创建顺序相同,对象的析构顺序与对象的销毁顺序相反。
比如说,如果一个类 `A` (包含类 `B` 和类 `C` 的对象作为成员),则在创建 `A` 的对象时,首先会调用 `B` 的构造函数,然后调用 `C` 的构造函数。
然后析构顺序就与构造顺序相反。也就说当销毁对象A时,析构函数会按照对象在类成员声明中的逆序依次调用。继续上面的例子,也就是说,他首先会调用 `C` 的析构函数,然后调用 `B` 的析构函数。
还有一种情况:就是父类和子类的析构与构造关系:
比如说现在有一个子类b,他继承了父类a,那么在创建子类b的对象时,
就会先调用父类a的构造函数,
再调用自己子类b的构造函数,
在析构的时候,顺序就反过来了,
就是先析构子类b,
最后再析构父类a
```cpp
Base::fun()
Child::fun()
~Child::fun()
~Base::fun()
```
## 10.stl:vector、list、Map的区别
vector:底层是一个动态数组,可以通过下标进行快速随机访问,占据连续的内存,在不扩容的情况下,在尾部增删很快.在扩容的情况下,需要先开辟原来容器大小的1.5倍,再将原数据拷贝到新的内存,最后在释放原内存
list:是一个双向链表,他虽然也可以用下标访问,但是那是因为他重载了中括号运算符,他访问一个元素的复杂度是o(n),他的内存是不连续的,节点之间通过指针连接.他唯一的优势是可以快速的在任意位置进行增删,但前提是先经过o(n)的复杂度找到这个位置
Map:是一个键值对,类似于json那种结构,底层是红黑树实现.
每个键都是唯一的(键和值可以为null,但是键只能出现一次),
map在插入好删除时会自动排序,他对元素的访问、插入和删除操作,这些操作的时间复杂度通常是对数时间(即`O(log n)`)。
```cpp
#include
#include