首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【C++】详解多态的底层原理

我们来看下结果是几 哦豁,答案是12字节。 怎么回事?为什么12呢?...所以多态时的函数调用不是在编译期间就能确定要调用函数了,而是在运行期间通对象里的虚函数指针找到虚表,然后确定要调用的具体函数。 那现在我们回过头来看多态的两个条件?为什么是它们两个?...那第二个为什么必须是父类的指针或引用去调用函数呢? 因为父类的指针和引用是不是既可以指向子类对象,也可以指向父类对象啊,我们之前学过,它支持赋值转换(切片)嘛。...但是int*解引用是个int,形参本质是个函数指针,所以我们可以再强转一个 这样。 那我们运行试一下: 可以,我们看到Derive类对象里面就是有三个虚函数地址的。...我们看到,现在第一个位置确实不是之前的0了,大家看这个值转化成10进制是几? fffffffc,内存中是补码,转换为10进制是-4。 那这个数是干嘛的呢?

33410
您找到你想要的搜索结果了吗?
是的
没有找到

python3--中的进程操作--multiprocess模块

需要使用关键字的方式来指定参数 2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号 参数介绍: 1 group参数未使用,值始终为None 2 target表示调用对象,... name为子进程的名称 方法介绍 1 p.start():启动进程,调用该子进程中的p.run()  2 p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法...id号     time.sleep(10)  # 延迟10秒 print(os.getppid())  # 打印父进程id号 p = Process(target=process1)  # 实例化一个对象...id号, getppid父进程id号     time.sleep(10)  # 延迟10秒 print(os.getpid())  # 打印进程id号 if __name__ == '__main...为什么打印两次进程id号?

1.3K10

【C++】从零开始认识多态

我们运行看看: 多态调用运行时,到指定对象的虚表中找虚函数调用(指向基类调用基类的虚函数,指向子类调用子类的虚函数) 普通调用:编译时,调用对象是哪个类型,就调用它的函数。...0; i< 100000 ; i++) { Person* p2 = new Student; delete p2; } return 0; } 如果我们在Student中申请一个空间,析构的时候却不能调用析构函数俩把申请的空间...在内存窗口里存在4个函数指针,接下来我们来验证一下他们是不是对应的虚函数。 虚函数表本质是一个函数指针数组! 那么如何定义一个函数指针和函数指针数组呢?...也很特别) typedef void(*VFPTR)(); VFPTR p1; VFPTR p2[10]; 那么如果我们想要打印出虚表,我们可以设置一个函数: //因为是函数指针数组,所以传参是函数指针的指针...所以应该是: 12 (B类) + 12(C类) + 8(A类的int)+ 4(D类的int) = 36 那为什么A会有一个虚表指针,不是D类有!?

7710

人人都能看懂的 Python 装饰器入门教程!

本文我将尝试说清楚为什么需要现装饰器、什么是装饰器、以及如何写一个简单的装饰器,但要彻底理解装饰器还要从函数开始说起,下面是有关函数的四个重要的概念,希望大家可以明白。...func2 >>> func2(func1,3,4) 函数 func2 正在执行 函数 func1 正在执行 7 可以看到,先执行func2,在func2接收到fun1后,再次执行func1返回。...说明func2只能在func1中被调用!....func2(b)> >>> func3(2) 函数 func2 正在执行 3 从上面的运行结果可以看到,当执行func1(1)后,返回的是func2的地址,赋给func3,之后执行...至此,我想你应该明白为什么需要现装饰器、什么是装饰器、以及如何写一个简单的装饰器,当你再次看到装饰器时,脑海中浮现的概念应该不仅仅是@。

50120

【多态】【虚表指针与虚表】【多继承中的多态】

为什么运行结果: 12 我们通过定义一个基类 Base 的对象,通过监视窗口来看看是什么情况: Base b; 咦,很奇怪是不是?...: A::fun() B::fun() 下图分别对三种情况进行解析: 接下来我们再来思考一个问题:为什么一定要求说要用父类的指针或引用去调用函数不是父类的对象?...void PrintVFT(VFunc* ptr) //这里ptr是个存函数指针的数组指针 { // 依次取虚表中的虚函数指针打印调用。...void PrintVFT(VFunc* ptr) //这里ptr是个存函数指针的数组指针 { // 依次取虚表中的虚函数指针打印调用。...,为了加上相隔的字节数,所以我们得将 &d 转化为 char*。

1.1K30

C++:深入理解多态

) ,如果没有发生多态的话,那么就会去看调用者的类型不是去看指向对象的类型,从而导致指向对象没有被析构,造成内存泄露。...,没有重写就失去了意义,最好的方法其实是编译器对没重写的虚函数进行报错,但是之前在这方面没有去严格地限制说不重写就会报错,所以这边做了一个妥协就是你可以通过增加override来帮助你检查,防止你写漏...动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态(运行时)。...在某些函数必须出现在代码段(常量区)的时候,inline会妥协失去作用 5. 静态成员可以是虚函数吗?...如果是父类指针对象或者是引用对象,则调用的普通函数快,因为构成多态,运行调用函数需要到虚函数表中去查找。 10. 虚函数表是在什么阶段生成的,存在哪的?

6500

一篇文章你明白python的装饰器

10然后打印6,其实这里就是涉及到变量作用域的问题 当Python编译函数的的定义体的时候,它判断b是局部变量,毕竟在函数中有b = 9表示给b赋值了,所以python会从本地环境获取b,当我们调用方法执行的时候...,定义体会获取打印变量a的值,但是当尝试获取b的值的时候发现b没有绑定值,所以要想上述代码运行还可以把b设置为全局变量,或者把b赋值放到调用之前 函数对象的作用域 python中一切皆对象,同其他对象一样...,函数对象也有使用的范围即函数对象的作用域。...x print(func2(5)) func1() print(func2(5)) 这个例子中我们在def func1函数内可以调用fun2,但是我们在外面是无法调用func2的,所以结果为看到如下...avg(10)的时候make_averager函数已经返回了,它的本地作用域也一去不复返,但这里其实series是自由变量,是指未在本地作用域绑定的变量 我们可以通过print(dir(avg)),看到如下结果

75810

Python学习(五)---- 不可不知的装饰器!

把一个函数名当做实参传给另外一个函数(不修改被装饰的函数源代码的情况下为添加功能) 2.2 返回值中包含函数名 ? 运行结果: ?...把函数内存地址都打印出来了,看到这么多内存地址,有什么想法? 加上小括号就能运行。 上面代码“test2(func2())” 和 “test2(func2)”有什么区别?...加上小括号是函数返回结果,不加是函数内存地址。所以加上小括号就不符合高阶函数定义了。 既然以后有了函数的内存地址,是不是可以赋值给其他变量? ? 好像还没什么用,怎么他有用呢?...把test2(func2)赋值给func2 ? 这就是高阶函数的第二个好处:返回值中包含函数名(不修改函数调用方式) ---- 3....别忘记了,第二种方式,高阶函数要加上return,如下 ? 虽然没有修改源代码和调用方式,但是函数加上return,函数就结束了,然卵。怎么实现呢?

40120

python入门到放弃-函数专题

wan() 3.准备开始执行函数 4.打印,今天一起去玩 5.打印,去哪里完 6.打印,我不知道 7.函数执行完毕,本次调用完毕,wan()函数调用完毕 '''...("hahaha") # func2(func1,func) # 我是func2 # 我是func1 # 我是func # hahaha #解释:首先执行func2函数,有两个实参传递给形参,打印我是func2...,然后使用inner()调用 # print(func) # ret = func() # ret() # func()() #先运行func() 然后再返回值上加() 六.函数的嵌套 1.主要遇见()...fun5,打印二哈,接着调用fun1,打印蒋小雨,然后调用fun3的函数打印张冲 #接着执行下面函数体代码块,调用fun4,打印龙大队,接着调用fun2打印鲁炎 七.命名空间 把存放名字和值的关系的空间叫做命名空间...outer()函数更改为20,然后再调用outer_2函数打印30 # 这样就会出现哪个先调用就执行那个,所以改来改去是很混乱的 # def outer(): # a = 10

1.8K30

C++-带你走进多态(2)

另外Func2继承下来后是虚函数,所以放进了虚表,Func1也继承下来了,但是不是虚函 数,所以不会放进虚表。 4....满足多态以后的函数调用不是在编译时确定的,是运行起来以后到对象的中取找的。不满足多态的函数调用时编译时确认好的。 4.3 动态绑定与静态绑定 1....动态绑定又称后期绑定(晚绑定),是在程序运行期间,根据具体拿到的类型确定程序的具体行为,调用具体的函数,也称为动态多态。...那么我们如何查看d的虚表呢?下面我们使用代码打印出虚表中的函数。...4.虚表指针传递给PrintVTable进行打印虚表  typedef void(*VFPTR) (); void PrintVTable(VFPTR vTable[]) { // 依次取虚表中的虚函数指针打印调用

6710

【C++】多态

我们看运行结果: 通过运行结果调试窗口我们可以看到,Base 类的大小是 12 字节,比我们预期的 8 字节多了四字节,这 其实是因为 Base 类中还存在一个默认的虚函数表指针 vfPtr,该指针指向一个虚函数表...注意:有的老铁可以认为虚表如果在代码段是不是就不能对进行覆盖了,其实不是的,子类的虚表是先拷贝父类虚表,然后进行覆盖,覆盖完毕后才存储到代码段中的。...(一个在编译时就确定函数地址,后面运行时直接调用该地址;一个在运行时才去别处取函数的地址进行调用) 拓展思考:为什么父类对象不能实现多态,而必须是父类的指针/引用?...)(); void PrintVTable(VFPTR vTable[]) { // 依次取虚表中的虚函数指针打印调用调用可以看出虚表中存的是哪个函数 cout " <...如果虚函数不是多态调用,则一样块;如果虚函数是多态调用,则普通函数访问更快,因为虚函数多态调用需要运行时到虚表中去取虚函数的地址,然后再 call。 虚函数表是在什么阶段生成的,存在哪的?

44900

C++之多态

基类的成员函数Func2被派生类继承下来,由于是虚函数,所以进入虚函数表; 基类的成员函数Func3也被派生类继承下来,由于不是函数,所以没有进入虚表。...: 可以看到Person对象和Student对象调用同一个函数Func得到不同的结果,这是因为基类调用函数的传参基类对象,派生类对象调用函数时的传参是派生类对象中基类的那一部分。...满足多态以后的函数调用不是在编译时确定的,是运行起来以后到对象的中取找的(动态绑定);不满足多态的函数调用是在编译时就确定的(静态绑定)。...我们可以将这个现象理解为一个Bug,并不是派生类的虚表里没有它自己的虚函数,而是这两个虚函数被监视窗口隐藏了。那么如果我们想查看派生类的虚函数都有那些该如何进行查看呢?...void PrintVTable(VFPTR vTable[]) { // 依次取虚表中的虚函数指针打印调用

33540

C++【多态】

如何判断函数调用关系?...若满足多态:看指向对象的类型,调用这个类型的成员函数 不满足多态:看具体调用者的类型,进行对应的成员函数调用 2.2、虚函数及重写 所以什么是虚函数?...func1(); p2->func1(); delete p1; delete p2; return 0; } 通过汇编代码观察: 注:下图中的函数地址仅供参考,与上图中的调用演示并不是同一次运行...p2->func1(); add(1, 2); add(1.1, 2.2); 简单来说,静态绑定就像函数重载,在编译阶段就确定了不同函数调用动态绑定是虚函数调用过程,需要 虚表指针+虚表,在程序运行时...、如何使用多态、构成多态的两个必要条件及两个例外该,最后还学习了多继承模式下多态引发的相关问题,探究了原理。

11930
领券