C++隐藏规则

在面向对象的开发过程中,经常出现类的继承,这里面出现的成员函数的重载(overload)、覆盖(override)与隐藏(hidden)很容易混淆。首先澄清这3个概念:重载覆盖(派生类函数覆盖基

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

 在面向对象的开发过程中,经常出现类的继承,这里面出现的成员函数的重载(overload)、覆盖(override)与隐藏(hidden)很容易混淆。

首先澄清这3个概念:

 

重载

  1. 相同的范围(在同一个类中)
  2. 函数名字相同
  3. 参数不同
  4. virtual 关键字可有可无

覆盖(派生类函数覆盖基类函数)

  1. 不同的范围(分别位于派生类与基类)
  2. 函数名字相同
  3. 参数相同
  4. 基类函数必须有 virtual 关键字

 

隐藏(派生类的函数屏蔽了与其同名的基类函数)

  1. 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无 virtual 关键字,基类的函数将被隐藏(注意别与重载混淆)
  2. 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

下面用一个简单的例子来阐述

#include <iostream>  
using namespace std;  
class Base  
{  
public:  
    virtual void vf(float x) { cout << "Base::vf(float) " << x << endl; }  
    void g(float x) { cout << "Base::g(float) " << x << endl; }  
    void h(float x) {cout << "Base::h(float) " << x << endl; }  
};  
class Derived : public Base  
{  
public:  
    virtual void vf(float x) { cout << "Derived::vf(float) " << x << endl; }  
    void g(int x) { cout << "Derived::g(int) " << x << endl; }  
    void h(float x) { cout << "Derived::h(float) " << x << endl; }  
};  
  // http://www.cnblogs.com/roucheng/
int main()  
{  
    Derived d;  
    Base *pb = &d;  
    Derived *pd = &d;  
    // Good : behavior depends solely on type of the object  
    pb->vf(3.14); // Derived::vf(float) 3.14  
    pd->vf(3.14); // Derived::vf(float) 3.14  
    // Bad : behavior depends on type of the pointer  
    pb->g(3.14); // Base::g(float) 3.14  
    pd->g(3.14); // Derived::g(int) 3 (suprise!)  
    // Bad : behavior depends on type of the pointer  
    pb->h(3.14); // Base::h(float) 3.14 (suprise!)  
    pd->h(3.14); // Derived::h(float) 3.14  
    return 0;  
}  

 例子中,pb和pd指向同一地址,按理运行结果是相同的,但其实却不是。由于隐藏机制的作用,部分方法的调用依赖于所使用的指针!

 

由此看来,隐藏机制似乎会带来不少理解上的问题,但“存在即合理”:

  1. 写语句pd->f(10)的人可能真的想调用Derived::f(char *)函数,只是他误将参数写错了。有了隐藏规则,编译器就可以明确指出错误,这未必不是好事。否则,编译器会静悄悄地将错就错,程序员将很难发现这个错误,留下祸根
  2. 假如类Derived有多个基类(多重继承) ,有时搞不清楚哪些基类定义了函数f。如果没有隐藏规则,那么pd->f(10)可能会调用一个出乎意料的基类函数f,而隐藏规则的存在消灭了这个问题

 

总结

     工欲善其事,必先利其器。弄清楚这些基本概念,才能在实践中少走弯路。

http://www.cnblogs.com/roucheng/p/3470287.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120617.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • CPLD和FPGA的区别(2)

    CPLD和FPGA的区别(2)可编程逻辑器件主要包括FPGA和CPLD,FPGA是FieldProgrammableGateArray缩写,CPLD是ComplexPromrammableLogicDevice的缩写。   从可编程逻辑器件的发展历史上来讲,CPLD一般是指采用乘积相结构的基

    2022年5月5日
    37
  • 动漫迷必备网站[通俗易懂]

    动漫迷必备网站[通俗易懂]nyaa这是个比较全的网站,里面包含动漫、游戏、同人,二次元和三次元都有。https://nyaa.si/NeetsNeets你的私人追剧专家,包含日剧、韩剧、美剧、动漫以及国产剧等,链接都是由用户上传的,资源比较丰富。http://neets.cc/哈哩哈哩H小站也是一个不错的选择,界面偏暖色调,个人比较喜欢。http://www.halihali.cc/天马…

    2022年8月23日
    4
  • node 的运行命令

    node 的运行命令node 的运行命令

    2022年4月23日
    360
  • APAP INCLUDE「建议收藏」

    APAP INCLUDE「建议收藏」*&———————————————————————**&ReportYMWXBINCLUDE*&*&———————————————————————**&…

    2022年9月22日
    0
  • android退出app的方法,Android 实现彻底退出自己APP 并杀掉所有相关的进程[通俗易懂]

    android退出app的方法,Android 实现彻底退出自己APP 并杀掉所有相关的进程[通俗易懂]彻底杀掉App相关进程的代码publicvoidkillAppProcess(){//注意:不能先杀掉主进程,否则逻辑代码无法继续执行,需先杀掉相关进程最后杀掉主进程ActivityManagermActivityManager=(ActivityManager)CurrentActivity.this.getSystemService(Context.ACTIVITY_SERVIC…

    2022年7月17日
    14
  • angular框架如何实现父子组件传值、非父子组件传值

    angular框架如何实现父子组件传值、非父子组件传值文章目录1.理解父子组件、非父子组件2.父组件给子组件传值–@input3.父组件通过@ViewChild主动获取子组件的数据和方法4.非父子组件如何传递数据1.理解父子组件、非父子组件什么是父子组件?组件的父子关系是相对来说的,即在一个A组件中嵌入了B组件,那么在这一层关系中,A组件是B组件的父组件,B组件是A组件的子组件。看下面两幅图即可理解:app.component.html与普通组件的关系:普通组件与普通组件:现在应该知道父子组件是什么关系了,关键看谁嵌入了谁那里。父子组件

    2022年5月13日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号