当前位置: 首页 > wzjs >正文

成都网站seo排名优化做网站用什么程序

成都网站seo排名优化,做网站用什么程序,深圳网络营销和推广渠道,福田瑞沃自卸车C 运行时多态与函数调用机制详解 1. 重载与覆盖的对比重载示例覆盖示例 2. 运行时多态的本质3. 虚函数表的实现机制代码示例运行结果 虚函数表(vtable)和虚指针(vptr)的实现Base 类的内存布局Derived 类的内存布局 动态绑定的过程 4. 关键问题解答为什么 Base 的析构函数需要是…

C++ 运行时多态与函数调用机制详解

    • 1. 重载与覆盖的对比
      • 重载示例
      • 覆盖示例
    • 2. 运行时多态的本质
    • 3. 虚函数表的实现机制
      • 代码示例
        • 运行结果
      • 虚函数表(vtable)和虚指针(vptr)的实现
        • Base 类的内存布局
        • Derived 类的内存布局
      • 动态绑定的过程
    • 4. 关键问题解答
      • 为什么 `Base` 的析构函数需要是 `virtual`?
      • 虚函数表是否会影响性能?
    • 5. C 语言的函数调用过程
      • 栈帧(Stack Frame)的结构
      • 栈帧的创建过程
        • 1. 初始状态(`main()`开始执行)
        • 2. `func(3, 5)`被`main()`调用
        • 3. `func`开始执行
        • 4. `func`执行完毕,准备返回
      • 函数调用流程示意图
        • 函数调用前(`main()`运行中)
        • 调用 `func(3, 5)`
        • `func`执行完毕,返回`main()`
    • 6. 总结
      • 关于虚函数表和运行时多态
      • 关于函数调用机制

1. 重载与覆盖的对比

特性重载(Overloading)覆盖(Override)
关系类型同一个类中的水平关系父子类之间的垂直关系
方法数量多个方法之间的关系一个方法或一对方法之间的关系
决定机制根据调用的实参表和形参表选择方法体根据对象类型(对象对应存储空间类型)决定
确定时间编译期确定运行时确定
目的提供多种实现同一功能的方法,适应不同参数类型或数量通过多态性允许子类提供与父类不同的行为

重载示例

int add(int a, int b) {return a + b;
}double add(double a, double b) {return a + b;
}

覆盖示例

class Base {
public:virtual void print() const {std::cout << "Base class" << std::endl;}
};class Derived : public Base {
public:void print() const override {std::cout << "Derived class" << std::endl;}
};

2. 运行时多态的本质

C++ 运行时多态(动态绑定)的核心在于:

  • 函数调用的确定时间不同

    • 静态绑定(编译时多态):编译阶段确定函数调用,如函数重载、模板等
    • 动态绑定(运行时多态):运行时根据对象类型决定函数调用,如继承加虚函数
  • 实现方式

    • C++ 通过**虚函数表(vtable)和虚指针(vptr)**来支持动态绑定

3. 虚函数表的实现机制

代码示例

#include <iostream>class Base {
public:virtual void show() { std::cout << "Base::show()" << std::endl; }virtual void display() { std::cout << "Base::display()" << std::endl; }virtual ~Base() {}  // 析构函数设为虚函数,保证子类对象析构正确
};class Derived : public Base {
public:void show() override { std::cout << "Derived::show()" << std::endl; }void display() override { std::cout << "Derived::display()" << std::endl; }
};int main() {Base* b = new Derived();b->show();     // 调用 Derived::show()b->display();  // 调用 Derived::display()delete b;      // 确保正确调用 Derived 析构函数return 0;
}
运行结果
Derived::show()
Derived::display()

虚函数表(vtable)和虚指针(vptr)的实现

Base 类的内存布局
成员地址/偏移量说明
vptr 指针0x1000指向 Base 的虚函数表
Base::show()0x2000在 vtable 中的第 1 个槽位
Base::display()0x2008在 vtable 中的第 2 个槽位
Derived 类的内存布局
成员地址/偏移量说明
vptr 指针0x3000指向 Derived 的虚函数表
Derived::show()0x4000覆盖 Base::show()
Derived::display()0x4008覆盖 Base::display()

说明

  • BaseDerived的对象中,都有一个隐藏的虚指针(vptr),用于指向该类的虚函数表(vtable)
  • BaseDerived各自的vtable存储了类的虚函数地址,按声明顺序存储
  • 当子类重写虚函数时,子类的vtable替换了父类vtable中对应函数的地址

动态绑定的过程

Base* b = new Derived(); 时:

  1. b实际存储的是 Derived 对象,但指针类型是Base*
  2. b指向Derivedvptr,即b->vptr = &Derived_vtable
  3. 调用b->show();的步骤
    • b通过vptr找到Derivedvtable
    • vtable第 1 个函数地址指向Derived::show()
    • 最终调用Derived::show(),而不是Base::show()

同理,b->display();也会调用Derived::display()

4. 关键问题解答

为什么 Base 的析构函数需要是 virtual

Base* b = new Derived();
delete b;  // 调用 ~Base() 还是 ~Derived()?

如果 ~Base() 不是虚函数

  • delete b;只会调用Base::~Base()不会调用Derived::~Derived(),可能导致内存泄漏

如果 ~Base() 是虚函数

  • vtable记录Derived::~Derived()的地址,delete b;时会正确调用Derived::~Derived()确保正确析构

虚函数表是否会影响性能?

  • 额外的内存开销

    • 每个对象多了一个vptr 指针(通常 4/8 字节)
    • 每个类多了一个vtable(存储在静态存储区)
  • 额外的函数调用开销

    • 虚函数调用需要间接寻址(查表)
    • 比普通函数调用多一次指针解引用(比直接调用慢)
    • 但现代 CPU对间接寻址优化较好,性能损失很小(一般小于 10%)

如果在性能关键代码中,可以:

  • 减少不必要的虚函数(用final禁止继承优化)
  • 避免小函数的虚拟调用(如inline + constexpr)
  • **使用 CRTP(Curiously Recurring Template Pattern)**避免虚函数

5. C 语言的函数调用过程

C 语言的函数调用依赖**栈(Stack)**来管理参数传递、局部变量存储以及返回地址保存。每次函数调用都会创建一个栈帧(Stack Frame),它是管理函数执行所需信息的结构。

栈帧(Stack Frame)的结构

一个函数的栈帧通常包括以下部分(从高地址到低地址):

栈帧组成部分作用
返回地址存储调用者的返回地址(即call指令保存的地址)
上一帧指针(EBP)记录前一个函数的EBP,用于恢复调用者的栈环境
函数参数存储传递给被调用函数的参数(按调用约定决定具体位置)
局部变量存储该函数的局部变量,占用栈上的空间
临时寄存器保存区存放函数调用前需要保存的寄存器值(如EBX, EDI, ESI等)

💡 栈的增长方向

  • 通常栈从高地址向低地址增长,即新数据压栈时地址递减

栈帧的创建过程

假设我们有如下代码:

#include <stdio.h>void func(int a, int b) {int sum = a + b;  // 局部变量printf("sum: %d\n", sum);
}int main() {func(3, 5);return 0;
}

main()调用func(3, 5)时,栈的变化如下(以x86体系结构为例):

1. 初始状态(main()开始执行)

ESP(栈指针)EBP(帧指针)仅用于main函数本身的运行,假设栈的初始状态如下:

高地址 → ────────────────────────| main() 的返回地址     |
EBP →   | main() 的上一帧指针   |
ESP →   | main() 局部变量        |
低地址 → ────────────────────────
2. func(3, 5)main()调用

main()调用func(3, 5)时,CPU 会执行call func,在栈上创建func的栈帧

高地址 → ───────────────────────────| main() 的返回地址          |
EBP →   | main() 的上一帧指针        || main() 局部变量            || ───────────────────────── || `func` 返回地址 (main 的下一条指令) || `func` 的上一帧指针(原 EBP)  |
ESP →   | `func` 的参数:b=5           || `func` 的参数:a=3           |
低地址 → ───────────────────────────
  • ESP递减,为func分配空间
  • EBP保存了main的栈帧起始位置,方便返回时恢复
3. func开始执行

func内部操作

int sum = a + b;  // 分配局部变量 sum

栈帧更新如下:

高地址 → ───────────────────────────| main() 的返回地址          |
EBP →   | main() 的上一帧指针        || main() 局部变量            || ───────────────────────── || `func` 返回地址 (main 的下一条指令) || `func` 的上一帧指针(原 EBP)  || `func` 的参数:b=5           || `func` 的参数:a=3           |
ESP →   | `func` 局部变量:sum=8       |
低地址 → ───────────────────────────

总结

  • EBP指向func栈帧的起始位置,作为稳定访问基点
  • ESP指向当前栈顶(sum 变量的地址),局部变量从ESP递减分配
4. func执行完毕,准备返回

函数返回前:

  1. EBP还原(恢复mainEBP)
  2. ESP还原(回到func调用前的位置)
  3. 从栈中弹出返回地址,并跳转到main()继续执行
高地址 → ────────────────────────| main() 的返回地址     |
EBP →   | main() 的上一帧指针   |
ESP →   | main() 局部变量        |
低地址 → ────────────────────────

ESPEBP恢复到main之前的状态main()继续执行。

函数调用流程示意图

函数调用前(main()运行中)
[  main() 栈帧  ]
┌────────────────┐
│   返回地址      │
├────────────────┤
│   旧 EBP       │
├────────────────┤
│   局部变量      │ ← ESP
└────────────────┘
调用 func(3, 5)
[  func() 栈帧  ]
┌────────────────┐
│   返回地址      │
├────────────────┤
│   旧 EBP       │
├────────────────┤
│   参数 b = 5   │
├────────────────┤
│   参数 a = 3   │
├────────────────┤
│   sum = a + b  │ ← ESP
└────────────────┘
func执行完毕,返回main()
[  main() 栈帧  ]  (恢复到原状态)
┌────────────────┐
│   返回地址      │
├────────────────┤
│   旧 EBP       │
├────────────────┤
│   局部变量      │ ← ESP
└────────────────┘

6. 总结

关于虚函数表和运行时多态

  1. **虚函数表(vtable) + 虚指针(vptr)**是 C++ 运行时多态的核心机制
  2. 对象存储vptr,指向其类的vtablevtable记录虚函数的地址,从而实现动态绑定
  3. 调用虚函数时,通过vptr查找vtable,获取函数地址并执行,实现运行时的多态
  4. 子类重写父类虚函数时,子类的vtable会替换相应的函数地址,确保Base*指向Derived调用Derived的实现
  5. 析构函数必须是virtual,否则会导致内存泄漏
  6. 虚函数带来一定的性能开销,但一般可接受,可通过finalCRTP等方式优化

关于函数调用机制

  1. 栈帧用于管理函数调用的状态

    • 参数传递(存储参数)
    • 局部变量存储(避免全局变量污染)
    • 返回地址管理(确保返回调用点)
    • 寄存器保存(保证函数调用前后的环境一致)
  2. 栈指针ESP

    • 指向栈顶(最近的局部变量或保存值)
    • 动态变化,函数执行时不断调整
  3. 帧指针EBP

    • 指向当前栈帧的基地址,用作稳定的访问基点
    • 调用新函数时会保存旧的EBP,方便恢复调用者栈帧
  4. 函数调用和返回的流程

    • call指令参数入栈跳转到目标函数
    • ret指令恢复EBP弹出返回地址回到调用处

文章转载自:

http://FClk4InU.mnwmj.cn
http://NdzffjYe.mnwmj.cn
http://BcgZEuUh.mnwmj.cn
http://HIHCaHmg.mnwmj.cn
http://eQt0S6kc.mnwmj.cn
http://kCObbx63.mnwmj.cn
http://w5TKHhlL.mnwmj.cn
http://DwVJCRir.mnwmj.cn
http://5JMtR3WC.mnwmj.cn
http://Iq4sCLAe.mnwmj.cn
http://sINwZIwK.mnwmj.cn
http://1wKftOst.mnwmj.cn
http://EACvjMxA.mnwmj.cn
http://yTZuIeKe.mnwmj.cn
http://xj4XuB8p.mnwmj.cn
http://lw0tpuAj.mnwmj.cn
http://m853Htzx.mnwmj.cn
http://NgF9RYpD.mnwmj.cn
http://5zW5DX92.mnwmj.cn
http://832BBOeO.mnwmj.cn
http://n4CDynXz.mnwmj.cn
http://n2Nw9F0r.mnwmj.cn
http://65RD9nzU.mnwmj.cn
http://wwITaTch.mnwmj.cn
http://gsSEdCiA.mnwmj.cn
http://2EZQEX2n.mnwmj.cn
http://PKRd6KEt.mnwmj.cn
http://1my6wgPJ.mnwmj.cn
http://j6rauAJs.mnwmj.cn
http://w6wSUWhs.mnwmj.cn
http://www.dtcms.com/wzjs/689851.html

相关文章:

  • 长沙做网站竞网衡阳网站建设价格
  • 百度推广建设网站是干什么了wordpress 截取中文
  • 中小型网站开发seo薪酬如何
  • 做国际贸易的有哪有个网站网站建设公司咨
  • 优秀手机网站设计途牛电子商务网站建设
  • 云梦网站建设国外免费源码网站
  • 如何破解网站管理员登陆密码可以建微信网站的
  • 北京网站手机站建设公司个人网页设计模板教程
  • 代做网站排名2021年有没有人给个网站
  • 金华高端网站建设公司定州国际陆港项目
  • 网站添加合适图片网络推广服务协议
  • 国外购物网站欣赏印章在线制作软件
  • 湖南天辰建设责任公司网站旅游网站总结
  • 安国手机网站设计优化电脑的软件有哪些
  • 北京网站设计制作哪个公司好旧笔记本 做网站
  • 网站界面大小网站常用架构
  • 重庆营销型网站建设沛宣河南工程建设协会网站
  • 中山网站开发wordpress文章末尾添加版权声明
  • 苏州手机网站建设费用凡科网站做门户网怎么样
  • 机械 网站源码wordpress 短信 插件
  • 成免费crm推广网站东海军事新闻最新消息
  • 自己做网站卖矿山设备济南物流公司网站建设
  • 上海建材网站房子简装修效果图片
  • 微信公众号做微网站吗云南昆明百度总代理
  • 在线营销型网站2021能看的网站不要app贴吧
  • 外网不能访问wordpress深圳优化企业
  • 基础网站建设的实施步骤开封到濮阳
  • 外国扁平化网站全国一级建造师网
  • 吉安企业做网站网站开发用什么语言比较流行
  • 长沙网站优化安徽网络优化公司排名