C++,虚函数,

“如果派生类提供了虚函数的重定义,该虚函数表将保存新函数地址,否则保存函数原始版本地址,如果派生类定义了新的虚函数,则该函数的地址也被添加到虚函数表中。”——《c++pr... “如果派生类提供了虚函数的重定义,该虚函数表将保存新函数地址,否则保存函数原始版本地址,如果派生类定义了新的虚函数,则该函数的地址也被添加到虚函数表中。”——《c ++ primer plus》
我理解是为:派生类重新定义了基类虚函数,则在派生类虚函数表中,用新虚函数的地址替换基类虚函数的地址,如果派生类定义了新的虚函数,则将地址添加到表中。
但问题是,如果派生类定义的虚函数与基类虚函数名字相同,但是参数不同,这属于替换原基类版本,还是添加到表中?
展开
 我来答
人人顺风顺水
2019-04-04 · TA获得超过164个赞
知道小有建树答主
回答量:315
采纳率:77%
帮助的人:113万
展开全部

如果派生类定义了一个与基类同名,但具有不同参数的函数,这个函数究竟有没有被加入到派生类的虚函数表中?答案是yes。注意,不是虚函数就不来凑这个热闹了。

#include "pch.h"
#include <string>
#include <iostream>

using std::cout;
using std::endl;
class brass
{
private:
int a;
public:
brass() :a(5) 
{
};
virtual void with()
{
cout << a << endl;
}
};

class brassplus : public brass
{
private:
int b;
public:
brassplus() :b(6) 
{
};
virtual void with()
{
cout << "1:" << b << endl;
}
virtual void with(int i)
{
cout << "2:" << b << endl;
}
};
int main()
{
brass* a;
brassplus b;

a = (brass*)&b;
a->with();
b.with(1);
b.brass::with();
}

口说无凭,现在我们就上vs2017调试器,揭开虚函数表的面纱。首先用鼠标在编辑器左栏下断点,断点下在brassplus b;一行,然后点击“本地Windows调试器”进入调试模式。

调试器运行到断点停了下来,此时brassplus b; 这行代码是未执行的,我们将对它单步执行。

单步执行的快捷键是F11。如果想一次执行完一个过程(或称为函数),则用它旁边的那个“逐过程”调试键(F10)。

连按几次F11,直到看到派生类b的成员b被初始化为6。看到红色地址0x00aff7ec了吗,这个地址就是派生类brassplus的对象b在内存中的起始地址。

我们在“内存窗口”的地址栏输入上述地址0x00aff7ec,看到了没有,第一个值(0x00b89b40)就是“虚函数表指针”,后面还跟着已经被分别初始化为5和6的两个类成员。如果你的c语言学得比较扎实,就应该知道所谓的指针就是内存中的地址,现在我们就去“虚函数表指针”指向的地址,看一看虚函数表中究竟包含了几项。

虚函数表包含了两项,分别是0x00b813a2和0x00b8125d,它们表示虚函数在内存中的位置。到了这里,我们已经肯定了开篇的结论。但为了加深初学者的印象,我们继续往下走几步。这两项中的每一项,更准确地说,表示了一个地址,即一条跳转指令在内存中的地址,cpu执行完这条跳转指令就能顺利跳到虚函数在内存中的真正位置。现在我们到这两个地址看一看。

为了把指令弄明白,我们使用反汇编窗口,内存窗口更适于看数据。看到了吧,0x00b813a2所在位置是一条jmp跳转指令,执行了它会跳到哪里去呢?调试器已经帮我们算出来了,是0x00b82890。

在0x00b82890,我们看到了虚函数virtual void with()的实现。

同理,第二项0x00b8125d,所在处是一条jmp指令,跳转至0x00b827e0。

在0x00b827e0,我们看到了虚函数virtual void with(int i)的实现。

最后把上面说的内容总结一下,借几天前画的一张图。总之,在上机后,书中的任何错误和含糊之处就会暴露无疑,每纠正一个错误,你就比别人更前进一步。

GTA小鸡
高粉答主

2019-04-04 · 醉心答题,欢迎关注
知道大有可为答主
回答量:2.6万
采纳率:78%
帮助的人:1.3亿
展开全部
两个函数名称相同而参数不同,属于函数重载,会被编译器认为是两个不同的函数。这是C++基础。
追问

  你说的对,在普通情况,这样是属于重载,但这里是类继承,我就搞不明白了

追答

在任何情况都属于重载。

如果子类重载的虚函数和父类的重名,那子类的重载虚函数将隐藏父类的版本。

注意分清隐藏和覆盖的区别,隐藏可以通过显式地指定类域来调用被隐藏的函数。

已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式