什么是多态?
编译时多态与运行时多态 1. 编译时多态含义 编译时多态(Static Polymorphism)是在编译阶段通过函数或操作的重载、模板等机制实现的多样化行为。 也称为静态多态,因为函数调用在编译时就绑定(静态绑定)。 实现方式 函数重载:根据参数类型或数量选择不同函数。 运算符重载:自定义运算符行为。 模板:通过模板参数生成不同类型的函数或类(模板特化)。 特点 效率高:编译时解析,无运行时开销。 类型固定:需要在编译时确定调用类型。 无虚函数:不涉及虚函数表(vtable,参考上下文)。 代码示例12345678910111213141516#include <iostream>// 函数重载void print(int x) { std::cout << "Int: " << x << "\n"; }void print(double x) { std::cout << "Double: " << x...
虚函数与虚函数表
C++ 中的多态、虚函数、虚函数表、虚函数表指针和虚析构函数以下是对 C++ 中多态、虚函数、虚函数表(vtable)、虚函数表指针(vptr)以及虚析构函数的详细介绍,使用 Markdown 格式,包含代码示例和 LaTeX 表示(若适用)。内容基于 C++ 的运行时多态机制,并结合上下文(如内存对齐、智能指针等)。 1. 多态含义多态(Polymorphism)是面向对象编程的核心特性,允许通过基类指针或引用调用派生类的行为。C++ 中的多态主要分为: 编译时多态:通过函数重载或模板实现。 运行时多态:通过虚函数和继承实现,依赖动态绑定。 运行时多态 通过基类指针或引用调用派生类的虚函数,根据对象的实际类型动态决定调用哪个函数。 依赖虚函数表和虚函数表指针实现。 数学表示对于基类指针 ( p ) 指向派生类对象,调用虚函数 ( f ),实际执行的函数为:[\text{Execute}(p \to f) = \text{Dispatch}(p.\text{vptr}, f)]其中,(\text{Dispatch}) 根据虚函数表解析具体函数地址。 2....
c++中的重写与重载
...
函数后面的const与noexcept
C++ 中函数后面的 const 和 noexcept 的含义在 C++ 中,函数声明或定义后添加的 const 和 noexcept 是函数修饰符,用于指定函数的行为和属性。 1. 函数后面的 const含义 成员函数限定符:const 出现在类成员函数的声明或定义后,表示该函数不会修改对象的非 mutable 成员变量。 承诺:调用该函数时,对象的状态(除 mutable 成员外)保持不变。 语义:用于声明“只读”成员函数,增强代码安全性。 实现机制 编译器将 const 成员函数的 this 指针视为 const T*(而非 T*),禁止修改非 mutable 成员。 可被 const 对象、引用或指针调用,而非 const 成员函数只能被非 const 对象调用。 代码示例12345678910111213141516171819#include <iostream>class MyClass { int x = 0; mutable int y = 0; // mutable 允许在 const 函数中修改public: ...
智能指针们与shared_ptr手撕
看柠檬微趣c++客户端一面面经,发现shared_ptr手撕不了一点,顺便再复习一下智能指针吧。(真是面试造火箭) 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192#include<cstddef>struct ControlBlock{ size_t shared_count;//引用计数 ControlBlock():shared_count(1){}};template <typename T>class Shared_ptr{private: T* ptr; ControlBlock* ctrl; void release()//一个私有的释放函数 { if(ctrl) ...
const和constexpr
constexpr 和 const 的区别在 C++ 中,const 和 constexpr 都用于定义常量,但它们的用途和行为有显著区别。 简单来说const可以是运行时变量也可以是编译时变量,而constexpr必须是编译时变量 而数组的大小这种就必须是编译时变量 以下是详细对比: 1. 定义和用途 **const**: 表示变量的值在初始化后不可修改(只读)。 可以用于运行时常量或编译时常量,具体取决于初始化方式。 适用场景:需要确保变量不被修改,但不一定要求编译时求值。 示例:123const int x = 10; // 编译时常量int y = 5;const int z = y; // 运行时常量(y 的值在运行时确定) **constexpr**: 表示变量或函数的值或结果必须在编译时可求值。 用于定义编译时常量或编译时计算的函数,确保结果在编译阶段确定。 适用场景:需要编译时常量(如数组大小、模板参数)或性能敏感的编译时计算。 示例:123constexpr int x = 10; // 编译时常量constexpr int square(int...
static
static 在 C++ 中的各种用法以下是 static 的主要用法,包括静态变量、静态全局变量、静态局部变量、静态函数、静态成员函数和静态成员变量的详细说明。 #include <iostream> #include <string> // 1. 静态全局变量(文件作用域) static int globalCount = 0; // 仅当前文件可见 // 2. 普通全局变量(对比) int nonStaticGlobal = 0; // 其他文件可通过 extern 访问 // 3. 静态函数(文件作用域) static void incrementGlobalCount() { globalCount++; std::cout << "Static globalCount: " << globalCount << "\n"; } class MyClass { private: // 4. 静态成员变量 ...
单例模式
单例模式(Singleton Pattern)是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。 在C++中,单例模式常用于需要全局唯一实例的场景,例如日志系统、配置管理器或数据库连接池。下面详细介绍其实现方法和作用。 单例模式的实现方法以下是几种常见的C++单例模式实现方式: 1. 懒汉式(Lazy Initialization)延迟初始化,在第一次使用时创建实例。需要注意线程安全问题。 1234567891011121314151617181920212223242526272829303132333435363738394041#include <iostream>#include <mutex>class Singleton {public: static Singleton* getInstance() { if (instance == nullptr) { // 第一次检查 std::lock_guard<std::mutex>...
三次握手与四次挥手
三次握手和四次挥手是计算机网络中鼎鼎大名的面试题,今天主播也来回答下 三次握手首先是握手的过程 1.客户端随机生成序列号,然后把序列号seq=x放进SYN报文,发送给服务端,客户端进入syn_sent阶段 2.服务端接收到SYN报文之后,确认ack=x+1,以及自己的seq=y,发送syn+ack报文,服务端进入syn_rcvd阶段 3.客户端收到syn+ack报文之后,将ack=y+1,发送ack报文,自身进入established阶段 4.服务端收到ack报文,也进入established阶段 tips:第三次握手是可以携带数据的,前两次不可以(因为通信能力和连接还未确定可靠,而第三次携带一些数据可以减少RTT次数,比如发送http请求) 那么为什么需要三次握手呢?1. 确保双向通信能力TCP 是全双工协议,允许数据在客户端和服务器之间双向传输。三次握手通过以下步骤验证双方的发送和接收能力: 第一次(SYN):客户端发送 SYN 包(seq=x),证明客户端能发送数据,服务器能接收。 第二次(SYN-ACK):服务器响应...
从源文件到可执行文件(编译之路)
从源文件到可执行文件(编译之路)被面试官狠狠拷打的亡羊补牢罢了 编译过程C++程序从源代码到可执行文件需要经过四个主要阶段: 预处理(Preprocess) 编译(Compilation) 汇编(Assembly) 链接(Linking) 预处理(Preprocess)这一步由预处理器完成,对源程序中的伪指令(以#开头的指令)和特殊符号进行处理。主要工作包括: 将所有的#define删除,并进行宏展开 处理所有条件编译指令,如#if、#ifdef、#ifndef、#else、#elif、#endif等 处理#include预编译指令,将被包含的头文件内容插入该位置,递归处理多重包含 处理其他宏指令,包括#error、#warning、#line、#pragma 删除所有注释(C++的//,C语言的/**/),通常用空格替代 添加行号和文件标识,便于调试和错误定位 保留所有的#pragma编译器指令 处理预定义的宏:如__DATE__、__FILE__等 预处理后的文件通常有.i或.ii(C++)扩展名,可以通过g++ -E source.cpp -o...




