免费注册 查看新帖 |

Chinaunix

广告
  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3002 | 回复: 8
打印 上一主题 下一主题

[C++] 关于C++ Primer中“通过基类调用被屏蔽的虚函数” [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-07-06 21:10 |只看该作者 |倒序浏览
在C++ Primer 15.5.4中有一个例子,看了很久没有看懂,请教一下大家(分割线中是书中的原话);
===============================================================
class Base {
     public:
         virtual int fcn();
     };
     class D1 : public Base {
     public:
          // hides fcn in the base; this fcn is not virtual
          int fcn(int); // parameter list differs from fcn in Base
          // D1 inherits definition of Base::fcn()
     };
     class D2 : public D1 {
     public:
         int fcn(int); // nonvirtual function hides D1::fcn(int)
         int fcn();    // redefines virtual fcn from Base
     };
从 Base 继承的虚函数不能通过 D1 对象(或 D1 的引用或指针)调用,因为该函数被 fcn(int) 的定义屏蔽了。

通过基类类型的引用或指针调用函数时,编译器将在基类中查找该函数而忽略派生类:

     Base bobj;  D1 d1obj;  D2 d2obj;
     Base *bp1 = &bobj, *bp2 = &d1obj, *bp3 = &d2obj;
     bp1->fcn();   // ok: virtual call, will call Base::fcnat run time
     bp2->fcn();   // ok: virtual call, will call Base::fcnat run time
     bp3->fcn();   // ok: virtual call, will call D2::fcnat run time
===============================================================

对于bp1和bp3,都没有问题,但是对于bp2 ,为什么是可以调用的,存在如下疑问:

1) bp2 实际指向的是D1 类型的对象,但是D1 类 中定义了fcn,屏蔽了Base中的fcn,为什么会调用Base中的fcn而不出错?
2) 对于“通过基类类型的引用或指针调用函数时,编译器将在基类中查找该函数而忽略派生类” 这句话,无法理解;对于虚函数,不是应该动态绑定吗?动态绑定的后果就是很有可能调用派生类中重新定义的虚函数;为什么这里讲“忽略派生类”? 如果忽略了派生类,如何实现动态绑定?



论坛徽章:
0
2 [报告]
发表于 2014-07-07 08:50 |只看该作者
UP, 都休假了?

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
3 [报告]
发表于 2014-07-07 09:23 |只看该作者
1、D1的fcn跟基类的fcn参数不一样,不能算屏蔽吧
2、 似乎话不对,bp3->fcn();不就是调用的派生类的么

论坛徽章:
0
4 [报告]
发表于 2014-07-07 09:36 |只看该作者
回复 3# hellioncu


1、D1的fcn跟基类的fcn参数不一样,不能算屏蔽吧
--->  这个不管是C++ primer还是effective C++ , 都有这样的说法,说是编译器做匹配的时候,首先看的是函数名,只要函数名一样,就算屏蔽了,前提是基类和派生类之间做选择;

2、 似乎话不对,bp3->fcn();不就是调用的派生类的么
--->  这个,我也觉得不对,但是书上就这么写的,头疼

论坛徽章:
1
技术图书徽章
日期:2014-03-06 15:32:30
5 [报告]
发表于 2014-07-07 13:05 |只看该作者
回复 4# listenxu


    两本书都没看过,1的说法,能把原话贴上来么?

论坛徽章:
0
6 [报告]
发表于 2014-07-07 14:09 |只看该作者
回复 5# selfrun


    The version of fcn in D1 does not redefine the virtual fcn from Base. Instead, it hides fcn from the base. Effectively, D1 has two functions named fcn: The class inherits a virtual named fcn from the Base and defines its own, nonvirtual member named fcn that takes an int parameter. However, the virtual from the Base cannot be called from a D1 object (or reference or pointer to D1) because that function is hidden by the definition of fcn(int).

D1 中的 fcn 版本没有重定义 Base 的虚函数 fcn,相反,它屏蔽了基类的 fcn。结果 D1 有两个名为 fcn 的函数:类从 Base 继承了一个名为 fcn 的虚函数,类又定义了自己的名为 fcn 的非虚成员函数,该函数接受一个 int 形参。但是,从 Base 继承的虚函数不能通过 D1 对象(或 D1 的引用或指针)调用,因为该函数被 fcn(int) 的定义屏蔽了。

=============================================================================================

以上是中英文版本;

论坛徽章:
6
技术图书徽章
日期:2013-11-13 11:11:27子鼠
日期:2014-02-20 17:54:13处女座
日期:2014-06-16 17:43:33午马
日期:2014-08-08 09:11:17未羊
日期:2014-08-10 11:57:072015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2014-07-07 17:41 |只看该作者
本帖最后由 littledick 于 2014-07-07 17:42 编辑

总是先使用自己类型定义的函数,如果没有才找基类的。
用指针或引用 调用本类型定义的虚函数的时候,才根据vt和rtti决定是哪个实现。
我是这样理解的。

论坛徽章:
1
技术图书徽章
日期:2014-03-06 15:32:30
8 [报告]
发表于 2014-07-09 09:33 |只看该作者
listenxu 发表于 2014-07-07 14:09
回复 5# selfrun

看最后一句,你对屏蔽这个词的理解有误,这里的屏蔽是指在D1类,使用D1对象引用或指针时,基类的同名虚函数被屏蔽

论坛徽章:
0
9 [报告]
发表于 2014-07-16 21:06 |只看该作者
回复 8# selfrun


    谢谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP