
大家好我是Halcyon.平安欢迎文末添加好友交流共同进步目录C中四种类型转换的使用场景?C中 volatile 关键字的作用什么是多态简单介绍下C的多态C中虚函数的原理C中构造函数可以是虚函数吗?C中析构函数一定要是虚函数吗?C什么场景下需要用到移动构造函数和移动赋值运算什么是C 中的虚继承?什么是C的函数重载它的优点是什么和重写有什么区别什么是C的运算符重载?目录C中四种类型转换的使用场景?static_cast日常类型转换比如int→double、void*→int*、子类指针→父类指针上行安全。相当于告诉编译器我知道在转啥放心转。dynamic_cast多态向下转型专用父类→子类。会运行时检查转不了返回nullptr所以比 static_cast 安全。前提是父类必须有虚函数。const_cast唯一能动const的。比如有个const变量要去掉只读属性就靠它。也能加 const。reinterpret_cast最暴力直接重新解释比特位。用于指针↔整型、int*→char*这种风马牛不相及的转换偏硬件底层慎用。一句话记static_cast日常用、dynamic_cast多态转、const_cast动const、reinterpret_cast玩比特。C中 volatile 关键字的作用防止编译器优化强制每次都从内存读、写变量而不是用寄存器里的缓存值。典型场景嵌入式里映射到硬件寄存器的变量、信号处理函数里改的变量。⚠️大坑C的 volatile不保证原子性、不保证线程同步想线程安全得用std::atomic或锁。这点和 Java 的 volatile 完全不一样面试时别说错了。什么是多态简单介绍下C的多态多态就是同一个接口不同行为分两种静态多态编译期决定函数重载、模板。编译时就知道调哪个效率高。动态多态运行期决定虚函数。用基类指针/引用调虚函数实际调的是子类重写后的版本。动态多态的好处代码写一份子类可以各自表现。比如所有形状都有draw()圆画圆、方画方调用方不用关心具体是啥形状。C中虚函数的原理每个有虚函数的类编译器会给它生成一张虚函数表vtable里面存着这个类所有虚函数的地址类只有一份。每个这种类的对象里面都会多藏一个虚表指针vptr指向自己所属类的 vtable每个对象一份。调用虚函数时通过对象的 vptr → 找到 vtable → 查到真实函数地址 → 调用。这就叫动态绑定运行时才决定调谁。C中构造函数可以是虚函数吗?不能。这是个先有鸡还是先有蛋的问题虚函数靠 vptr 工作而 vptr 是构造函数在执行时才初始化的。也就是说要先调构造函数才能有 vptr但调虚函数又要先有 vptr——死循环。所以构造函数不能是虚函数。C中析构函数一定要是虚函数吗?不是必须但作为基类的类强烈建议是。场景用基类指针delete一个子类对象时——析构是虚函数先调子类析构 → 自动链调基类析构 → 完整清理没泄漏。析构不是虚函数只调基类析构子类析构根本不执行子类里 new 的资源就泄漏了。经验只要这个类会被继承、会被多态使用析构函数就写成虚的。C什么场景下需要用到移动构造函数和移动赋值运算核心思想源对象马上要销毁与其深拷贝不如直接偷它的资源指针一交接源指针置空。典型场景函数返回大对象比如返回一个vector返回的是临时对象右值用移动省一次拷贝。STL容器扩容vector扩容要把旧元素搬到新内存用移动比拷贝快得多。临时对象赋值比如a b cbc是临时值偷它就行。自己写的类里持有堆资源如char*字符串、int*数组有拷贝构造就建议加移动构造。一句话能偷就别复制偷完把源指针置空。什么是C 中的虚继承?为了解决菱形继承A → B、A → C、B和C → D这样 D 里会有两份 A 的成员访问时二义性 内存浪费。虚继承让 D 里只保留一份 A称为虚基类由最远派生类 D 负责构造 A。classA{...};classB:virtualpublicA{...};// 注意 virtualclassC:virtualpublicA{...};classD:publicB,publicC{...};// D 里只有一份 A关键词菱形继承、virtual、一份共享基类。什么是C的函数重载它的优点是什么和重写有什么区别函数重载同一个作用域里函数名相同但参数不同个数/类型/顺序就构成重载。返回值不参与区分。voidprint(int);voidprint(double);voidprint(constchar*);原理编译器通过name mangling把同名函数改成不同的内部名字比如print_int、print_double编译期就决定调哪个。优点API 设计更直观调用方不用记一堆名字。比如print(1)、print(3.14)、print(hi)统一用 print 就行。重载 vs 重写override重载 overload重写 override位置同一个类/作用域父类与子类之间函数名相同相同参数必须不同必须相同关键字virtual 不强制必须是虚函数时机编译期运行期一句话重载是同名不同参凑一起重写是子类改父类的虚函数。什么是C的运算符重载?给已有的运算符 - * / [] () 等赋予针对自定义类型的新含义让自定义类的对象也能像内置类型一样自然地用运算符。classString{char*data;public:Stringoperator(constStringother);// s1 s2 拼接booloperator(constStringother);// s1 s2 比较charoperator[](inti);// s[i] 访问字符};形式返回类型 operator符号(参数列表) { ... }注意只能重载已有的运算符不能发明新的比如不能造**。这几个不能重载::作用域、.成员访问、.*、?:三目、sizeof。别滥用让去做减法是找骂语义要符合直觉。一句话让自定义类型也能用、、[]像内置 int、string 那样自然。