<为什么>要有virtual,及如何理解晚捆绑

本文探讨了C++中的虚函数机制与多态性的实现原理,解释了虚拟机制的作用及晚绑定的概念,通过示例说明了如何使用虚函数实现多态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下边要说的是我在语言学习过程中遇到一些不理解的问题,为什么要有virtual机制,还有什么是晚捆绑。我当时学到这的时候可能困惑了一段时间,后来经过继续学习测试等,得出了自己的结论,仅在这记录一下。没有太多的代码实例,更像是我在啰嗦一些东西。

先说virtual

说道virtual肯定就想到多态,virtual是c++ 实现多态的一种方法,为什么要有这样一套虚机制? 还是那些原则,代码复用 ”想用不变的代码去实现不同算法“,大概就是 懒吧。

举个简单的例子,(可能我现在在站的高度不够,理解范围有限,但这个例子至少是虚机制想要解决的问题中的一种)

有一个方法void test() 来测试不同国家的人说的语言,比如说有 Chinese  Japanese French 等几个类,类中都有一个speak() 方法

 然后可以考虑这样写

 void test(Chinese *p)

{

p->speak();

 void test(Japanese*p)

{

p->speak();

 void test(French *p)

{

p->speak();

这样可以达到测试每个对象所说语种的目的。 但这样看起来很不好,这几个函数,只有参数类型不一样,内部实现都一样。那么想  能不能把参数类型设置成某个特殊的类型,这个特殊的类型可以接收 Chinese  Japanese French 等这些类的对象,然后在调用speak时,根据我实际传进去的参数类型,再调用每个类中的speak方法。 如果可以的话就能只写一个函数,实现不同的测试了

void test (special_class *p)

{

p->speak();

}

virtual机制就解决了上述问题,可以弄一个human的基类  然后让Chinese  Japanese French这几个类继承它,  然后语法上允许父类指针指向子类对象

void test(human * p)

{

p->speak();

}

然后问题是 test既然是能处理不同子类对象,那它如何确定该调用哪个子类中的speak()?

这就需要 晚捆绑啊,函数覆盖啊  虚表啊什么的那一套来实现,这个不是我困惑的重点,关于虚表可以看看这个

点击打开链接



第二个  关于晚捆绑

学到这的时候我很是困惑,有早捆绑 或者叫 静态绑定,比如说上边的test 的参数 只是一个类类型  而不是指针或者引用的话,也就是说它没有多态,只能处理一种类型的对象,

这时候调用speak 就是静态绑定,在编译阶段就能完成。   如果有多态  那就叫晚捆绑(动态绑定)  绑定只能在运行时。困惑就在这了,

什么叫运行时才能绑定啊????



在我的程序运行之前,我的所有代码不是已经的写定了么,编译之后 已经生成了 那些固定的汇编语句了啊,还有什么是非得运行之后才确定么????

说是不知道函数要处理的是哪个具体的子类对象,所以确定不了调用哪个函数, 那既然我调用test的代码已经写了

比如     

Chinese  a;

test(a);

那函数要处理的对象不就是Chinese 类型的么   那就能确定调用的是Chinese 中的speak()了

编译时就把p->speak(); 换成 call(Chinese中speak的地址) 不就行了么,还有什么是在运行之前不能确定的呢?????

?????????????????????????????????????????????????????????????????????????????

当时确实很困惑啊,后来想想 too young too naive 啊

按照上边的想法,如果只调用test(a);

那是可以 把test函数中的speak调用改成call(Chinese中speak的地址),当程序执行到test(a);这句时 跳到改好的 test()函数的代码部分  能往下执行,并调用了正确的函数。只要再稍微往后想一点, test()都被改成了 针对对象a的特定版本了, 那还能调用它 来处理其他子类对象么? 不能处理了 ,那多态跑哪去了?

可见照上述我所想的这种静态绑定是实现不了多态的。 那多态是如何实现的,是靠动态绑定实现的,在c++编程思想中讲的比较明白了,为了实现多态,编译器在处理时会隐藏的插入一些内容


简单说,就是因为它不知道要处理的对象类型,不能直接去call某个函数的地址,它插入这段代码,如果是有虚机制的对象,那在对象存储空间里能找到v_ptr  也就是虚表指针,这个不管哪个子类的对象只要有virtual   都会有这个指针,然后通过这个指针的偏移处理,在虚函数表中找到要调用的具体版本的函数的地址,再 call     就能实现不管处理什么类型的子对象,都能找到v_ptr都能通过偏移 找到想要的函数,这就实现了 通用的处理。而这种处理方式,需要在程序运行是,找到传进来的那个具体对象的存储空间,然后在里边找到v_ptr 然后计算等等, 然后才能得到想要的函数, 也就可以理解 这是发生在运行时。



如果对这一块有疑惑,推荐去看c++编程思想第二版  第十五章



关于2023全国大学生电子设计竞赛的考题方向,作为一个 AI,我无法直接得知具体的考题方向。这些决策通常由组织者、教育机构或相关专家团队负责制定。他们会根据当前的技术发展趋势、行业需求以及学生的专业背景等因素来确定考题方向。 一般来说,电子设计竞赛的考题方向可能涵盖以下几个方面: 1. 器件与路设计:这包括子器件的选择与应用、路设计与优化等内容。参团队需要设计符合特定需求的路,并能够解决实际问题。 2. 嵌入式系统设计:嵌入式系统是现代子产品中不可或缺的一部分,涉及到硬件与软件的结合。参团队可能需要设计具有特定功能的嵌入式系统,并能够进行系统调试与优化。 3. 通信与网络应用:随着物联网和互联网技术的快速发展,通信与网络应用也成为电子设计竞赛的重要方向。参团队可能需要设计具有通信功能或者网络应用的子设备。 4. 创新设计与应用:鼓励参团队提出独特的创新设计,并能够将其应用到实际生活中,解决现实问题或改善人们的生活质量。 需要注意的是,具体的考题方向可能会根据每年的竞赛主题和当前的技术热点而有所不同。如果您想获取关于2023全国大学生电子设计竞赛的详细信息,建议您关注相关竞赛组织方或教育机构的官方公告和通知。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值