数码视讯 C++开发 一面
1. C++ 多态
答案:C++ 多态分编译时多态和运行时多态。编译时多态主要是函数重载、模板,运行时多态主要是虚函数。面试里一般问的还是运行时多态,也就是基类指针或者引用指向子类对象,调用重写后的函数。它的核心价值是接口统一、实现可替换,在客户端开发里像渲染对象、组件系统、资源加载器这类设计都很常见。多态成立的前提一般是继承、虚函数重写、父类指针或引用调用。
代码:
#include <iostream>
using namespace std;
class Base {
public:
virtual void draw() { cout << "Base draw" << endl; }
virtual ~Base() {}
};
class Sprite : public Base {
public:
void draw() override { cout << "Sprite draw" << endl; }
};
int main() {
Base* p = new Sprite();
p->draw();
delete p;
return 0;
}
2. 计算机怎么存整数,补码讲一下,-1 怎么存,浮点数怎么存
答案:整数在计算机里本质上都是二进制存储。对于有符号整数,现代计算机基本都使用补码。补码的好处是把加减法统一了,硬件实现简单,而且零只有一种表示。正数的补码就是它本身,负数的补码是对应正数按位取反再加一。比如 8 位下,1 是 00000001,那 -1 的补码就是 11111111。浮点数一般按 IEEE 754 标准存,分成符号位、指数位、尾数位。像 float 通常是 32 位,double 通常是 64 位。浮点数不是精确存十进制小数,所以会有精度误差,这也是为什么 0.1 + 0.2 不一定严格等于 0.3。
3. 具体讲讲虚函数
答案:虚函数是 C++ 实现运行时多态的核心机制。一个类里只要有虚函数,编译器通常就会为这个类生成虚函数表,对象里会有一个虚表指针。当通过父类指针调用虚函数时,程序不是在编译期就确定调用哪个函数,而是运行时根据对象真实类型去虚表里查找。虚函数最常见的两个考点,一个是多态调用,另一个是虚析构。只要类要被当成基类使用,析构函数通常就应该写成虚函数,不然通过基类指针释放子类对象时可能析构不完整。另外构造函数里虽然能写虚函数调用,但那时候对象还没完全构造成子类语义,所以不会表现出完整的多态行为。
代码:
#include <iostream>
using namespace std;
class Base {
public:
virtual void func() { cout << "Base::func" << endl; }
virtual ~Base() { cout << "Base dtor" << endl; }
};
class Derived : public Base {
public:
void func() override { cout << "Derived::func" << endl; }
~Derived() { cout << "Derived dtor" << endl; }
};
int main() {
Base* p = new Derived();
p->func();
delete p;
return 0;
}
4. 智能指针,什么情况都能用智能指针吗
答案:常见智能指针有 unique_ptr、shared_ptr、weak_ptr。unique_ptr 表示独占所有权,shared_ptr 表示共享所有权,weak_ptr 主要是配合 shared_ptr 解决循环引用。但智能指针不是任何场景都能无脑用。如果资源所有权非常明确,用 unique_ptr 很合适;如果对象被多个地方共同持有,才考虑 shared_ptr;如果只是观察者,不想影响生命周期,就用 weak_ptr。一些场景下并不适合,比如对象生命周期由引擎统一管理、跨 DLL 边界释放规则不一致、或者性能特别敏感的高频小对象场景,滥用 shared_ptr 反而会带来额外开销。所以核心不是“能不能用”,而是“所有权模型和生命周期是否适合用”。
5. vector 扩容机制
答案:vector 的底层是连续内存。容量不够时会申请一块更大的新内存,然后把旧数据搬过去,再释放旧内存。扩容倍数标准库实现不完全一样,常见是 1.5 倍或者 2 倍增长,所以 push_back 的均摊复杂度是 O(1),但某一次扩容本身可能是 O(n)。扩容会导致原有迭代器、指针、引用失效,这个在项目里很容易踩坑。如果提前知道大概要放多少元素,最好先 reserve,这样能减少扩容次数和内存搬迁成本。
代码:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
cout << "size=" << v.size() << " cap=" << v.capacity() << endl;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
cout << "push " << i
<< ", size=" << v.size()
<< ", cap=" << v.capacity() << endl;
}
return 0;
}
6. 熟悉的排序算法,快排什么时候退化为 O(n²),怎么优化
答案:常见排序算法像冒泡、选择、插入、归并、快排、堆排我都比较熟。工程里如果问得稍微深入一
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏系统梳理C++方向, 大中厂高频高频面试考点 , 内容皆来自真实面试经历,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力.

查看12道真题和解析