百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

实现多态必须满足什么条件(实现多态的两种方式)

liebian365 2025-03-18 23:46 10 浏览 0 评论

虚函数机制 virtual mechanism

先看代码:

class A{public:

virtual void print() { cout<<"A.."<<endl; }

};class B : public A{public:

virtual void print() { cout<<"B.."<<endl; }

};

void test4()

{ A a1; //base

B b1;//child

a1 = b1;//A::operator= 对象b1赋值给a2

a1.print(); // prints A

A& a2=b1;// 引用a2指向b1

a2.print();//// prints B}

实现条件:

To get polymorphic behavior in C++, the member functions called must be virtualand objects must be manipulated through pointers or references

Q:

  • 为什么使用派生类和基类对象之间直接赋值不能实现?? 必须用用指针或者引用?

  • 为什么要用虚函数?

A:为什么使用派生类和基类对象之间直接赋值不能实现?? 必须用用指针或者引用?

要实现多态,必须使用指针或者引用 因为默认的赋值运算符并不会操作虚函数表

验证如下:[ Print C++ vtables using GDB]

  • 1.1 vptr 理解成指针 因为不知道vptr内部结果 采用 gdb x查看变量值

因为给出代码只提供一个函数 只需要打印4字节就可以了

(gdb) p sizeof(int) $10 = 4

1.2 打印 A a1; //base

(gdb) p a1

$11 = (A) { _vptr.A = 0x400e10 }

(gdb) x/4x 0x400e10

0x400e10 <_ztv1a+16>: 0x00400c9e 0x00000000 0x00004231 0x00000000

(gdb) x/4x 0x00400c9e

0x400c9e : 0xe5894855 0x10ec8348 0xf87d8948 0x400dd7be

父类A::_vptr.A 内容是:

0x400c9e

  • 1.3 打印 B b1;//child

执行构造函数:A() -> B() 初始化_vptr

(gdb) p b1 $12 = (B) { = { _vptr.A = 0x400df0 }, }

(gdb) x/4x 0x400df0

0x400df0 <_ztv1b+16>: 0x00400cc8 0x00000000 0x00000000 0x00000000

(gdb) x/4x 0x00400cc8

0x400cc8 : 0xe5894855 0x10ec8348 0xf87d8948 0x400ddbbe

这说明对象b1.vptr 记录虚函数入口地址 0x400cc8

只要a1.vptr 指向 b1.vptr 即可

  • 1.4 a1=b1

调用 A::operator=

a1 _vptr 没有发生变化

是不是复制操作有问题这个别人已经验证了

A& operator = (const B& b) { (int )this=(int )&b; return this; }

依然没有发生变化

  • 1.5 A& a2=b1; 发生发生了什么变化

(gdb) p (B*)a2 { = { _vptr.A = 0x400cc8 }, }

(gdb) x/4x 0x400cc8

0x400cc8 : 0xe5894855 0x10ec8348 0xf87d8948 0x400ddbbe

一句话解释:

1.默认的赋值运算符并不会操作虚函数表。
2.要实现多态,必须使用指针或者引用


  • 为什么要用虚函数?

如果不没有声明虚函数 同名函数出现覆盖现象!

A& a2=b1;

假如 b1 [AAAA BBBB]

a2 [AAAA]

A& a2=b1; 对象赋值 只是a.成员=b.成员 其他的就发生强制转换 结果 a2 [AAAA]

函数之间不会赋值的就需要一个记录 函数入口地址

图片可能和代码不符 你应该可以看懂

没有虚函数的对象数据布局

成员类型相同:

成员类型不同(对齐)

有虚函数的对象数据布局

有虚函数的对象数据布局

跟深入地方请查看《Inside the C++ Object Model》

我理解

数据部分:

对象在执行赋值 ==操作时候,如果类型不同会发生强制转换 因此需要相同成员

vptr比较特殊 不能像普通成员一样访问 只能通过指针来实现不同对象赋值

通过命令 gdb x 查看 我只声明一个virtual 因此 n=4

必须使用指针或者引用 为啥它可以如果有清楚麻烦留言告知!

相关推荐

C语言自学课程大纲(c语言入门自学资料)

一、自学C语言,很多人不知道应该如何学习,从哪儿学习,学习又分为几个阶段,总是学着学着就很迷茫???分享C语言的学习路线图,跟着路线图学吧,天天看。...

「linux」定时器方案:红黑树、最小堆和时间轮的原理

一、网络事件和时间事件对于服务端来说,驱动服务端逻辑的事件主要有两个,一个是网络事件,另一个是时间事件;...

程序员怎么会不知道 C10K 问题呢?

昨天的文章中提到了C10K问题,结果好些程序员跑过来问,啥是C10K,我写了这么多年程序,我怎么不知道呢?我说,那你听说过前腿儿猪肉吗?今天简单说说C10K的问题。关于这个问题,Ruby...

朝荐开源 - glib(朝廷百科)

glib是一套通用的实用程序库,它为C语言提供了许多有用的数据结构、工具函数和抽象层,旨在简化C语言的跨平台开发,并提高代码的可重用性和效率。glib是GTK+和GNOME桌面环...

libevent总结(事件处理框架)(libevent libev)

libevent的事件处理框架是一个反应堆模型,而反应堆模型的核心就是io复用,拿epoll来说反应堆模型有两个核心数据结构,一个是epoll维护的内核事件表,一个是保存激活事件的事件队列当然,值得注...

日荐开源 - LibEvent(aldente官网网址)

libevent...

快递单号一键查询,高效追踪包裹物流,省时省力!

在繁忙的现代生活中,快递已成为我们日常生活中不可或缺的一部分。然而,面对众多的快递单号,如何快速、准确地查询包裹的物流信息成为了一个难题。现在,我们为您带来了一款快递单号一键查询工具,让您的物流追踪变...

导入不同快递公司下的单号批量查快递动态,一键解决物流查询难题

看着满屏快递单号陷入沉思?同事小王已经用《快递批量查询高手》一键导入多家快递,批量查询快递信息并统计了…而你还在中通、圆通、申通官网来回切换到鼠标冒烟?是时候亮出这个让快递公司接口“集体颤抖”的...

一键解锁快递查询高效能:批量查询快递,智能排序延误单号

当你的客服团队还在用5个浏览器轮番刷新物流页面时,隔壁仓库的王叔已经用快递批量查询高手把多个个滞留件变成会说话的预警红点!这篇教程将揭秘物流圈的「神器」,让「未更新快递」自动排队到你面前认罪。1.在软...

一站式快递单号查询平台,修改单号刷新快递信息的快递查询教程

一站式快递单号查询平台,支持导入单号查询时修改快递单号,高效刷新快递信息的快递查询教程随着电子商务的繁荣发展,快递业务量不断增长,无论是电商卖家还是普通消费者,对快递信息的查询和管理需求都日益增强。为...

高效快递单号查询,批量查询快递信息,多种查看方式满足你的需求

最近有很多朋友在问,如何查快递,怎么根据条件查看单号呢?不知道如何操作的宝贝们,下面请随小编一起来试试,希望能给大家带来帮助。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?步骤1:运...

物流查询达人必备!一键批量查询快递单号,根据发出时间筛选单号

嘿,各位快递查询达人们,是不是经常为海量的快递单号查询而头疼不已?想要一款能够在线批量查询快递动态,还能根据发出物流时间一键筛选所需快递单号信息的神器吗?来来来,让我给你们揭秘一款快递批量查询高手软件...

快递查询神器,多单号导入,筛选保存一键完成

当面对如山的快递单号,你是否曾感到手足无措?每一个单号都需要你逐一输入、查询,再逐个根据时间差进行筛选,这样的工作无疑是对耐心与精力的双重考验。但别担心,今天,我们将为你揭示一款物流行业的秘密武器——...

快递单号查询神器:一键复制粘贴,轻松批量追踪同公司快递

嘿,小伙伴们!还在为手动输入快递单号查询物流信息而烦恼吗?是不是觉得每次都要一个个输入单号,既费时又费力?别急,今天我要给大家介绍一款神奇的软件——快递批量查询高手!这款软件就像你的私人快递助手一样,...

快递单号查询入口自动批量查询快递动态并根据派件员字段排序单号

想象一下,面对堆积如山的快递单号,你不再需要一个个手动输入查询,而是轻轻一点,就能瞬间掌握所有快递的物流动态,甚至还能根据派件员智能排序,让管理变得井井有条。这不再是遥不可及的梦想,快递批量查询高手软...

取消回复欢迎 发表评论: