公司网站制作有哪些注意事项烟台网站建设烟台

张小明 2026/1/13 0:32:16
公司网站制作有哪些注意事项,烟台网站建设烟台,个人网站做商城会怎样,精仿虎嗅网wordpress一. 纯虚函数与抽象类#xff1a;强制接口规范的“契约” 在实际开发中#xff0c;我们经常需要定义一个“只规定行为#xff0c;不提供具体实现”的类。C 通过纯虚函数和抽象类实现这种 “接口契约”。 本文代码示例所需头文件#xff1a; #includeiostream us…一. 纯虚函数与抽象类强制接口规范的“契约”在实际开发中我们经常需要定义一个“只规定行为不提供具体实现”的类。C 通过纯虚函数和抽象类实现这种 “接口契约”。本文代码示例所需头文件#includeiostream using namespace std;1.1 纯虚函数没有实现的 “接口声明”在虚函数的声明后加0该函数即为纯虚函数。纯虚函数无需在基类中实现语法上允许实现但无实际意义因为会被派生类重写其核心作用是“强制派生类必须重写该函数”。1.2 抽象类包含纯虚函数的 “不可实例化类”包含纯虚函数的类称为抽象类它有两个关键特性无法直接实例化对象编译器会报错派生类若未重写基类的所有纯虚函数自身也会成为抽象类同样无法实例化。有了上面的知识储备我们来看下代码示例吧// 抽象类包含纯虚函数Drive() class Car { public: // 纯虚函数只声明接口不提供实现 virtual void Drive() 0; }; // 派生类Benz重写纯虚函数成为“具体类” class Benz :public Car { public: // 必须重写Drive()否则Benz也是抽象类 virtual void Drive() { cout Benz-舒适 endl; } }; // 派生类BMW重写纯虚函数成为“具体类” class BMW :public Car { public: virtual void Drive() { cout BMW-操控 endl; } }; int main() { // 抽象类无法实例化对象 // Car car; // 用抽象类指针指向派生类对象多态核心用法 Car* pBenz new Benz; pBenz-Drive(); // 多态调用输出“Benz-舒适” Car* pBMW new BMW; pBMW-Drive(); // 多态调用输出“BMW-操控” return 0; }二. 多态的底层原理虚表指针与虚函数表当我们用基类指针调用派生类的虚函数时编译器如何 “知道” 该调用哪个类的函数答案藏在虚表指针vfptr和虚函数表vtable中 —— 这是 C 实现动态绑定运行时多态的核心机制。2.1 虚表指针vfptr对象中的 “导航器”首先通过下面这个题目来验证一下虚表指针的存在下面编译为32位程序的运行结果是什么DA. 编译报错 B. 运行报错 C. 8 D. 12class Base { public: // 虚函数触发编译器生成虚表指针 virtual void Func1() { cout Func1() endl; } virtual void Func2() { cout Func2() endl; } // 普通函数 void Func3() { cout Func3() endl; } protected: int _b 1; char _ch x; }; int main() { Base b; //除了我们能看到的_b和_ch其实有虚函数的类就会有一个虚函数表指针(32位下4字节,64位下8字节) //因为⼀个类所有虚函数的地址要被放到这个类对象的虚函数表中虚函数表也简称虚表。 cout sizeof(b) endl;//32位441-12 // 输出结果32位环境下为12字节64位环境下为16字节 return 0; }关键结论只要类中包含虚函数或继承自含虚函数的类该类的对象就会额外存储一个虚表指针虚表指针通常位于对象内存的最前端不同编译器可能有差异其作用是 “指向该类的虚函数表”同类型的对象共用一张虚函数表但每个对象都有独立的虚表指针指向同一张虚表。2.2 多态的实现原理从底层的角度Func函数中ptr-BuyTicket()是如何作为ptr指向Person对象调用Person::BuyTicketptr指向Student对象调用Student::BuyTicket的呢通过下图我们可以看到满足多态条件后底层不再是编译时通过调用对象确定函数的地址而是运行时到指向的对象的虚表中确定对应的虚函数的地址这样就实现了指针或引用指向基类就调用基类的虚函数指向派生类就调用派生类对应的虚函数。第⼀张图ptr指向的Person对象调用的是Person的虚函数第二张图ptr指向的Student对象调用的是Student的虚函数。class Person { public: virtual void BuyTicket() { cout 买票-全价 endl; } private: string _name; }; class Student : public Person { public: virtual void BuyTicket() { cout 买票-打折 endl; } private: string _id; }; void Func(Person ptr) { // 这里可以看到虽然都是Person指针Ptr在调用BuyTicket // 但是跟ptr没关系而是由ptr指向的对象决定的。 ptr.BuyTicket(); } int main() { // 其次多态不仅仅发⽣在派⽣类对象之间多个派⽣类继承基类重写虚函数后 // 多态也会发⽣在多个派⽣类之间。 Person ps; Student st; Func(ps); Func(st); ////这三个的虚函数表是一样的同类型的对象共用一虚表 //Person p1; //Person p2; //Person p3; return 0; }正确处理//方案 1用「基类引用」传参推荐更简洁 // 关键修改形参改为 Person基类引用 void Func(Person ptr) { ptr.BuyTicket(); // 触发多态由引用指向的实际对象类型决定调用版本 } int main() { Person ps; Student st; Func(ps); // 引用指向Person对象 → 调用Person::BuyTicket Func(st); // 引用指向Student对象 → 调用Student::BuyTicket return 0; } //方案 2用「基类指针」传参经典多态写法 // 关键修改形参改为 Person*基类指针 void Func(Person* ptr) { ptr-BuyTicket(); // 触发多态由指针指向的实际对象类型决定调用版本 } int main() { Person ps; Student st; Func(ps); // 指针指向Person对象 → 调用Person::BuyTicket Func(st); // 指针指向Student对象 → 调用Student::BuyTicket return 0; }2.3 虚函数表vtable存储虚函数地址的 “数组”虚函数表简称 “虚表”是编译器为每个含虚函数的类生成的一张 “虚函数指针数组”数组中存储的是该类所有虚函数的地址。其结构与生成规则如下基类虚表存储基类所有虚函数的地址如Base类的虚表存储Func1和Func2的地址派生类虚表首先继承基类虚表的所有内容若派生类重写了基类的虚函数会用派生类自身的虚函数地址 “覆盖” 基表中 对应的位置派生类新增的虚函数其地址会追加到虚表的末尾虚表结尾标记部分编译器如 VS会在虚表末尾添加0x00000000作为结束标记g 无此标记C 标准未强制规定。注意同类型的对象共用同一张虚表不同类型的对象都有各自独立的虚表。class Base { public: virtual void func1() { cout Base::func1 endl; } virtual void func2() { cout Base::func2 endl; } // 普通函数不存入虚表 void func5() { cout Base::func5 endl; } protected: int a 1; }; class Derive : public Base { public: // // 重写基类的func1会覆盖虚表中func1的地址 virtual void func1() { cout Derive::func1 endl; } // 派生类新增虚函数会追加到虚表末尾 virtual void func3() { cout Derive::func1 endl; } // 普通函数不存入虚表 void func4() { cout Derive::func4 endl; } protected: int b 2; }; int main() { Base b; Derive d; return 0; }2.4 动态绑定与静态绑定对不满足多态条件(指针或者引用调用虚函数)的函数调用在编译时绑定也就是编译时确定调用函数的地址叫做静态绑定。满足多态条件的函数调用是在运行时绑定也就是运行时到指定对象的虚函数表中找到调用函数的地址也叫做动态绑定。当用基类指针调用虚函数时编译器会按以下步骤完成 “动态绑定”运行时确定调用的函数获取虚表指针从基类指针指向的对象中取出虚表指针vfptr查找虚表通过虚表指针找到该对象所属类的虚函数表vtable定位函数地址在虚表中找到目标虚函数对应的地址若派生类重写过此处就是派生类函数地址调用函数通过找到的函数地址调用对应的虚函数。以之前的 “买票” 场景为例流程如下// 基类指针指向派生类对象 Person* ptr new Student; // 动态绑定流程 1. 从ptr指向的Student对象中取出vfptr 2. 通过vfptr找到Student类的虚表 3. 在虚表中找到BuyTicket对应的地址Student::BuyTicket的地址 4. 调用该地址对应的函数输出“买票-打折”。三. 关键问题辨析与总结3.1 虚函数存在哪里虚表又存在哪里虚函数与普通函数一样编译后是一段机器指令存储在代码段虚表中仅存储虚函数的 “地址”而非函数本身虚表本质是 “存储虚函数地址的指针数组”在 VS 等编译器中存储在代码段常量区因内容不可修改C 标准未强制规定存储位置不同编译器可能有差异。int main() { int i 0; static int j 1; int* p1 new int; const char* p2 xxxxxxxx; printf(栈:%p\n, i); printf(静态区:%p\n, j); printf(堆:%p\n, p1); printf(常量区:%p\n, p2); Base b; Derive d; printf(Base虚函数表地址:%p\n, *((int*)b)); printf(Derive虚函数表地址:%p\n, *((int*)d)); printf(虚函数地址:%p\n, Base::func1); printf(普通函数地址:%p\n, Base::func5); }运行结果栈:010FF954静态区:0071D000堆:0126D740常量区:0071ABA4Person虚表地址:0071AB44Student虚表地址:0071AB84虚函数地址:00711488普通函数地址:007114BF3.2 实战注意事项抽象类只能作为基类指针 / 引用使用不可直接实例化抽象类无法实例化派生类必须重写所有纯虚函数才能成为 “具体类”虚表指针会增加对象的内存开销32 位下 4 字节64 位下 8 字节虚函数调用比普通函数多一次 “地址查找”存在微小性能损耗但通常可忽略多态带来的灵活性远大于性能损失。四. 多态考察的一些常见问题(重点面试高频题)1. 面向对象的三大特性(这里重点讲讲什么是多态)封装将数据和操作数据的方法封装在一起隐藏对象的内部实现细节仅对外暴露公共接口降低耦合性(eg:迭代器的实现)继承子类继承父类的属性和方法子类可以直接使用父类的非私有成员和方法实现代码的复用同时子类可以对父类的方法进行扩展和重写多态多态分为静态多态(编译时多态)和动态多态(运行时多态)静态多态比如函数的重载模板。我们可以通过传不同的参数达到不同的效果。动态时多态就要求有继承关系用基类的指针或者引用去调用虚函数且派生类对基类的虚函数完成了重写根据基类的指针指向的对象去调用对应的方法做到不同对象执行不同逻辑。(eg.动物叫声的例子不同的对象发出不同的叫声)2. 什么是重载重写(覆盖)重定义(隐藏)重载同一类中(同一作用域中)函数名相同参数列表参数类型、个数、顺序不同返回值类型可以相同也可以不同重写(覆盖)子类继承父类后(不同作用域)对父类的虚函数进行重新实现函数名、参数列表、返回值类型协变情况除外完全相同。重定义(隐藏)(不同作用域)子类中定义了与父类同名(只需要同名就可以)的非虚函数隐藏父类的该函数。特性定义示例重载同一类中方法名相同参数列表参数类型、个数、顺序不同与返回值类型无关类中add(int a, int b)和add(double a, double b)重写覆盖子类继承父类后对父类的虚函数进行重新实现方法名、参数列表、返回值类型协变情况除外完全相同父类Animal的虚函数makeSound()子类Dog重写为void makeSound() { cout 汪汪 endl; }重定义隐藏子类中定义了与父类同名的非虚函数隐藏父类的该函数父类有func()子类也定义func()子类对象调用func()时执行子类的父类对象调用执行父类的3. 多态的实现原理答多态通过 虚函数表vtable和虚函数指针vptr 实现。每个包含虚函数的类都有一个虚函数表表中存储着该类所有虚函数的地址。每个对象都有一个虚函数指针指向所属类的虚函数表(相同类型的对象指向同一张虚函数表)。当通过父类指针或者引用调用虚函数时程序会根据指向的实际对象类型通过其虚函数指针找到虚函数表再找到对应的虚函数地址并调用从而实现运行时的多态。4. inline函数可以是虚函数吗inline属性和虚函数属性能同时存在吗答可以是虚函数从语法上看inline函数可以声明为虚函数但实际上编译器会忽略inline属性(inline一般展开是不需要地址的)将其当作普通虚函数处理。因为虚函数要放在虚表中去两者机制冲突也就是说inline属性和虚函数属性是不同时存在的。5. 静态成员可以是虚函数吗答不能静态成员函数属于类不属于某个对象没有this指针而虚函数的调用需要通过对象的虚函数指针来实现所以静态成员函数不能是虚函数。6. 构造函数可以是虚函数吗答不可以。因为对象中的虚函数指针是在构造函数初始化列表阶段才初始化的所以构造函数不能是虚函数。7. 析构函数可以是虚函数吗什么场景下析构函数是虚函数析构函数可以是虚函数。场景当存在继承关系且需要通过父类指针删除子类对象时为了确保子类的析构函数被调用需要将父类的析构函数声明为虚函数。例如父类Base子类Derived若用Base* p new Derived(); delete p;如果Base的析构函数不是虚函数只会调用Base的析构函数导致子类资源未释放若为虚函数则会先调用Derived的析构函数再调用Base的析构函数。8. 对象访问普通函数快还是虚函数更快答首先如果是普通对象调用的话两者是一样快的但如果是基类的指针或者引用去调用且构成了多态调用则调用的普通函数更快运行时调用虚函数需要到虚函数表中去查找有一定开销。使用场景普通函数调用机制虚函数调用机制性能差异根源普通对象调用编译时直接绑定函数地址直接跳转执行编译时直接绑定函数地址直接跳转执行无差异基类指针/引用多态调用编译时直接绑定函数地址直接跳转执行运行时通过vptr找vtable再找函数地址执行虚函数多了查表的运行时开销9. 虚函数表是在什么阶段生成的存在哪里的答虚函数表是在编译阶段生成的一般情况下是存在代码段(常量区)的。10. C菱形继承的问题虚继承的原理答菱形继承会导致数据冗余和二义性的问题虚继承则是通过虚基类指针和虚基表(不要把虚函数表虚函数指针和虚基表虚基类指针搞混了)实现的中间基类在继承时顶层基类时声明为虚继承这样可以保证顶层基类的成员只会有一份解决了数据冗余和二义性的问题。11. 什么是抽象类抽象类的作用答 包含纯虚函数形如virtual void func() 0;的类无法实例化对象。抽象类的作用是作为接口规范强制子类必须重写实现纯虚函数
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

网站建设与维护方式是什么如何申请成立公司

Perl高级编程:引用、多维数组与哈希引用详解 1. 引用与二维数组 在编程中,我们常常会遇到需要处理复杂数据结构的情况。在Perl里,引用和二维数组就是处理这类问题的强大工具。 1.1 引用的概念 引用在Perl里就像是Windows系统的快捷方式或者Mac系统的别名。想象一下,你有…

张小明 2025/12/23 12:54:24 网站建设

flask做克隆网站购物网站免费模板

在当今复杂多变的金融市场中,量化投资者往往关注收益和风险,却忽视了一个关键因素:流动性风险。数据显示,超过30%的量化策略失效源于流动性管理不当。本文将通过 gs-quant 工具包,深入解析如何构建有效的流动性风险管理…

张小明 2025/12/23 12:53:21 网站建设

做电影网站如何规避版权网站跳转怎么做

目录 手把手教你学Simulink--风电MPPT场景实例:基于Simulink的PMSG扰动观察法(DOA)MPPT动态响应仿真 一、引言:为什么选择扰动观察法(DOA)?——PMSG风电MPPT的“经典动态响应研究载体” 核心价值: 挑战: 二、核心原理:DOA的“扰动-观察-调整”动态逻辑 1. 控制思想:…

张小明 2025/12/28 17:35:26 网站建设

可以左右滑动的网站全局右下角弹窗wordpress

摘要:AI CRM系统正成为销售流程智能化升级的关键。原圈科技通过AI CRM系统,将销售对话分析与业务流程深度融合,实现从基础转录到智能洞察再到自动化行动的闭环。原圈科技不仅提升销售效率,更通过私域AI能力底座保障数据安全&#…

张小明 2025/12/23 12:51:14 网站建设

怎么做新网站的推广微信公众号推广平台

还在为英雄联盟繁琐的操作流程烦恼吗?LeagueAkari作为基于LCU API开发的完整工具集,能够彻底改变你的游戏体验。这款免费开源软件提供战绩查询、自动秒选、游戏流程自动化等强大功能,让普通玩家也能享受职业选手般的操作效率。 【免费下载链接…

张小明 2025/12/23 12:49:08 网站建设

北京公司请做网站工资页面异常导致本地路径泄漏 wordpress

Wan2.2-T2V-A14B模型输出色彩空间管理的最佳实践 在AI生成内容迈向影视级制作的今天,一个看似微小却影响深远的技术细节正逐渐浮出水面:生成视频的颜色到底准不准? 当你用最先进的文本到视频(T2V)模型生成一段“夕阳下…

张小明 2025/12/23 12:48:05 网站建设