• C++隐藏机制


    大家都觉得很自然,但是没有注意到一个小插曲,就是这个foo()触发的隐藏机制: 派生类的foo()由于函数名,参数与基类都相同,然而又没有virtual修饰,因此不可避免地会触发隐藏。
    (一旦有virtual修饰就成覆盖了!搞不清楚隐藏何时触发的同学请百度:重载、覆盖、隐藏的区别)
     
     问题是,看到有同学问: 为什么此处触发隐藏了,p和ptr在调用foo()的时候仍然调用基类的,不是被隐藏了么???
     这么问的原因是,很多同学知道了有隐藏这么回事,但是不清楚隐藏触发后会发生什么。 隐藏机制触发之后,指针的调用取决于指针的类型。如果定义的是派生类指针,则该基类成员不可见(隐藏),但是若为基类指针,该基类成员仍然是可见的啊!因为此处的p和ptr均为基类指针,只是分别指向了基类和派生类对象,所以调用foo()的时候仍然是基类的成员。
    但是如果定义个派生类指针pb,如下:
     B *pb=&b;
     pb->foo(); 
    这时只会调用派生类的foo(),虽然B继承自A,但是基类的foo()会被隐藏。 
    这样看起来似乎莫名其妙,因为你想当然地认为派生类的指针肯定调用自己的成员啊,隐藏存在的意义是什么?就像此题,不用考虑它我也能做对!
     
    但是一旦foo()里有参数的时候,你就会大吃一惊!
    假设A中为void foo(float a),B中为void foo(int a): 
     做如下调用: 
    B *pb=&b; 
    pb->foo(3.14); 
    到底会调用谁?你可能会想: 首先foo()成 员不是虚函数,但是B继承A,B中有两个foo(),调用foo(3.14)时根据参数类型应该匹配基类的void foo(float)成员。 
    然而并不是!
    因为触发了隐藏机制,基类的void foo(float)会被隐藏,所以即使你调用foo(3.14)仍然只会调用派生类的void foo(int)成员。 
    你的惊讶正好解释了隐藏机制存在的意义。
    (PS:牛客网上C/C++专项训练上有专门一道题考察这种情况,当时解释里提出隐藏机制时大多数人也是一脸懵逼)  
     
    总结:
    1.判断要点:如果不是重载也不是覆盖,派生类和基类中一旦出现同名函数,一定触发隐藏机制(这是个简便判断技巧,你可以考虑除去重载和覆盖的任何同名函数情况,一定满足隐藏机制触发的两条规则)。
    2.隐藏触发的结果:指针对成员的函数调用取决于指针类型。
    若本身是基类指针(不管指向基类还是派生类)则仍然调用基类成员(不会牵扯到派生类,此处是隐藏,和多态没关系,按第1点已说明隐藏的触发可以首先排除覆盖,也就是多态问题);
    若本身是派生类指针,这时你就会看到隐藏的威力!此时不是简单地继承基类的成员,然后根据参数匹配调用,而是隐藏基类成员,只会调用派生类成员。
  • 相关阅读:
    MVC+jQuery开发B/S系统②:表单绑定
    插入排序
    笔记:实例管理
    文件读写冲突的解决办法:ReaderWriterLock
    MVC+jQuery数据绑定①:列表绑定(二)
    MVC+jQuery数据绑定①:列表绑定(三)
    非递归求 T(n) = [T(n1),n,T(n1)] 已知T1=[1]
    笔记:契约总结
    面试题:1~ n1 有n个数,是有序的,找出重复的那个数。
    Thread系列——ThreadPool
  • 原文地址:https://www.cnblogs.com/fenglongyu/p/7624353.html
Copyright © 2020-2023  润新知