问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

谁知道 C++ 中 虚函数的工作机制????

发布网友 发布时间:2022-03-18 00:38

我来回答

5个回答

懂视网 时间:2022-03-18 04:59

虚函数实现了c++的多态的机制,多态就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。

  在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体};实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。下面来看一段简单的代码。当将基类中的某一成员函数声明为虚函数后,派生类中的同名函数(函数名相同、参数列表完全一致、返回值类型相关)自动成为虚函数。

热心网友 时间:2022-03-18 02:07

C++类对象在内存中分配很复杂,静态变量和一半的函数存储在类的信息中,而非静态变量和虚函数存储在对象中。类对象不只是存储成员变量,对象中存储一个虚函数表的指针,即:vtbl,虚函数表中就存储着虚函数的指针,多少个虚函数就有多少项。但vtbl是一个指向虚函数表的指针,所以对象内存不变,变化的只是虚函数表。而继承、多态的机制就是靠这个虚函数表实现的。
派生类将虚函数重载时,会将虚函数表中此虚函数对应的函数指针修改。
所以将此派生类对象地址赋值给基类指针时,虚函数表中的函数指针并没有改变,所以用基类指针调用此虚函数其实调用的是派生类实现的函数。这就实现了多态。
而将派生类对象赋值给基类对象是,成员变量存在cut,会丢失派生类多于的数据,而虚函数表是不会复制的,虚函数表是按照基类创建的,所以将派生类对象复制给基类对象不能实现多态调用。
具体中间原理特别复杂,我也只了解大概。
推荐看一本书《Inside C++ Object Modol》,将的是C++对象的内部实现机制。很好的一本书。中文版侯捷翻译。叫《深入探索C++对象模型》

热心网友 时间:2022-03-18 03:25

从语言和概念的角度来说,子类继承父类是继承了所有protected和public非static成员(static成员是共享而不是继承),而成员包括函数和数据。所以从概念上来说,成员函数和成员变量都被继承了。
从实现上来说,实现要在外显上不违反概念,在内部可以非常随意。所有的实现子类继承父类成员函数只是子类共享了父类的函数,没有两份拷贝。编译器知道父类的某成员函数的地址,那么在子类调用父类的该方法时,编译器只要产生
call 函数地址 的代码就可以调用父类的方法,完全没有必要保留两份拷贝。
换句话来说,非虚方法的调用在编译时就已经确定了,编译器掌握一切信息。编译器选择最高效的实现(只保留一份函数拷贝)来符合C++语言概念。从逻辑上认为子类继承了父类的方法。

对虚函数,如果是在子类对象上用.操作符调用虚函数,那么编译器可以确定函数地址,此时不需要使用虚函数调用机制。只有在基类指针上用->操作符调用虚函数时,才会使用虚函数调用机制。此时编译器不知道基类指针指向具体什么类型的对象,所以它不知道到底调用哪个函数,它产生类似如下代码:
call [vftable + functionoffset]
也就是通过虚函数表中对应函数偏移来调用,虚函数表的布局是编译器已知的。当具体某个对象构造时,他们初始化虚表使得其中指针都指向自己的虚函数。这样就通过这个实现来满足了C++的虚函数概念。

举个例子:
class base {
private:
int member1;
protected:
int member2;
public:
int fun();
virtual int virtualfun();
};

class derive : public base {
public:
int member;
public:
virtual int virtualfun();
};

在代码中使用:derive test;
(以微软c/c++编译器为例)那么test在内存中可能是如下布局:
110000 vftable----------->112000
110004 base::member1
110008 base::member2
11000c derive::member
----------------------------
112000 (vftable[0])derive::virtualfun------>410000
----------------------------
410000 int derive::virtualfun()
410500 int base::virtualfun()
411000 int base::fun()
另外,团IDC网上有许多产品团购,便宜有口碑

热心网友 时间:2022-03-18 05:00

从语言和概念的角度来说,子类继承父类是继承了所有protected和public非static成员(static成员是共享而不是继承),而成员包括函数和数据。所以从概念上来说,成员函数和成员变量都被继承了。
从实现上来说,实现要在外显上不违反概念,在内部可以非常随意。所有的实现子类继承父类成员函数只是子类共享了父类的函数,没有两份拷贝。编译器知道父类的某成员函数的地址,那么在子类调用父类的该方法时,编译器只要产生
call 函数地址 的代码就可以调用父类的方法,完全没有必要保留两份拷贝。
换句话来说,非虚方法的调用在编译时就已经确定了,编译器掌握一切信息。编译器选择最高效的实现(只保留一份函数拷贝)来符合C++语言概念。从逻辑上认为子类继承了父类的方法。

对虚函数,如果是在子类对象上用.操作符调用虚函数,那么编译器可以确定函数地址,此时不需要使用虚函数调用机制。只有在基类指针上用->操作符调用虚函数时,才会使用虚函数调用机制。此时编译器不知道基类指针指向具体什么类型的对象,所以它不知道到底调用哪个函数,它产生类似如下代码:
call [vftable + functionoffset]
也就是通过虚函数表中对应函数偏移来调用,虚函数表的布局是编译器已知的。当具体某个对象构造时,他们初始化虚表使得其中指针都指向自己的虚函数。这样就通过这个实现来满足了C++的虚函数概念。

举个例子:
class base {
private:
int member1;
protected:
int member2;
public:
int fun();
virtual int virtualfun();
};

class derive : public base {
public:
int member;
public:
virtual int virtualfun();
};

在代码中使用:derive test;
(以微软c/c++编译器为例)那么test在内存中可能是如下布局:
110000 vftable----------->112000
110004 base::member1
110008 base::member2
11000c derive::member
----------------------------
112000 (vftable[0])derive::virtualfun------>410000
----------------------------
410000 int derive::virtualfun()
410500 int base::virtualfun()
411000 int base::fun()
另外,站长团上有产品团购,便宜有保证

热心网友 时间:2022-03-18 06:51

类中的函数,只有名,没有内容,访问对象时
仍被调用,目的是让你的实际函数取代虚函数,
扩大功能。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
苹果电脑电池充不进电苹果电脑充不进去电是怎么回事 苹果电脑不充电没反应苹果电脑充电指示灯不亮充不了电怎么办 狗狗更加忠诚护家、善解人意,养一只宠物陪伴自己,泰迪能长多大... 描写泰迪狗的外形和特点的句子 国外留学有用吗 花钱出国留学有用吗 !这叫什么号 百万医疗赔付后是否可以续保 前一年理赔过医疗险还能续保吗? 医疗住院险理赔后还能购买吗? 求问,C++中纯虚函数的实现原理是什么,即C++通过什么样的机制来实现这个功能的?不是问它的作用是什么。 手机突然从4G变成E是什么意思? 4G网上的好好的,突然变成“E”是啥意思 Viⅴo27移动4g变成e怎么解决? 苹果4G变E了怎么切换回来? 为什么手机网络突然从4G变成一个E了 手机信号突然从4G变成“E”,这是啥意思? 4G变e怎么变回来 华为手机4g变e怎么恢复 我的手机从4G变成了E后在信号强的地方都不自动转换成4G怎么办 手机突然连不上4g网络变成了E是什么意思 手机4g信号变成了E而且变不回来了 iPhone6S装的移动卡,突然由4g变成了E,变不回去了 中国移动4G 突然变成E了.什么情况? 移动4g变成e怎么解决 中国移动4G 突然变成E了.什么情况 移动4g变成e怎么解决? 手机4g忘了6变成e了 也变不回来了? 开启了4g但是一变成e就变不回来是怎么回事 英特尔i5 9300H核心数是多少? c++中,虚函数的运行机制是什么 C++中虚函数的作用是什么?它应该怎么用呢? C语言问题虚函数的问题 虚函数的实现方式和C语言中的哪个数据类型相似 c加加多态的种类,各自实现的机制 c/c++高手帮忙!!!c++中的virtual函数究竟是怎么实现的,用 C 语言表达出来,代码请加注释。 面向对象多态机制中,多个子类以不同的方式实现了父类里的虚函数,子类对象要调用父类中的虚函数时,父类 c++虚函数的说明 c++中什么是实函数 什么是虚函数 Objective-C有虚函数的概念吗? C++虚函数问题,续函数如何运行的机制 C++中虚函数的作用是什么?定义是什么?简要说明下,并举一个简单的例子? c++虚函数是干什么的?我没看懂,谁能给我讲一下 在C++中用虚函数的作用是什么?为什么要用到虚函数 c 虚函数的作用举例? 苹果7查询序列号出现无法验证产品购买日期是怎么回事啊 苹果序列号无法验证购买日期怎么办? 买的apple airpodspro官网查询序列号之后显示购买日期未验证是什么意思? 苹果序列号无法验证购买日期怎么办 官网查询序列号,提示让我验证购买日期是什么鬼