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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 开源视频会议BigBlueButton 0.81二次开发API

    开源视频会议BigBlueButton 0.81二次开发API开源视频会议BigBlueButton0.81二次开发API本文是copy一位博友的,为了不丢失这篇文章,谢谢。BigBlueButton是一个视频会议软件,它的演示环境和开发环境的搭建,网上都有很多的资料,为了便于二次开发,我整理了一下BBB的常用功能API接口,供参考:BigblueButton调用API,只需一个HTTP请求一个URL,查询参数提供呼叫所需要的信

    2022年7月14日
    29
  • 经典游戏—贪吃蛇从C++代码实现[通俗易懂]

    经典游戏—贪吃蛇从C++代码实现[通俗易懂]小时候都玩过贪吃蛇这个经典的小游戏,在我们的普通手机里似乎都是必备的。它伴随着我们的童年,经历了好多好多时光。它带给我们了许多的乐趣。学习了c++这门编程语言后,我就想着能不能把它做出来,在我查看了相关知识后,明白了其中的道理,就尝试着自己写出这个小游戏来,而且加入了许多可玩性的东西,包括等级选择,暂停/继续和分数制。整个程序采用了类和数组的相关知识实现。//=====================================

    2022年5月9日
    55
  • acwing292. 炮兵阵地(状态压缩dp+滚动数组)[通俗易懂]

    acwing292. 炮兵阵地(状态压缩dp+滚动数组)[通俗易懂]司令部的将军们打算在 N×M 的网格地图上部署他们的炮兵部队。一个 N×M 的地图由 N 行 M 列组成,地图的每一格可能是山地(用 H 表示),也可能是平原(用 P 表示),如下图。在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队);一支炮兵部队在地图上的攻击范围如图中黑色区域所示:如果在地图中的灰色所标识的平原上部署一支炮兵部队,则图中的黑色的网格表示它能够攻击到的区域:沿横向左右各两格,沿纵向上下各两格。图上其它白色网格均攻击不到。从图上可见炮兵的攻击范围不受地形的影响

    2022年8月9日
    9
  • 不要看《深入浅出MFC》![通俗易懂]

    不要看《深入浅出MFC》![通俗易懂]   开篇先声明一点,《深入浅出MFC》是一本不错的书,对于MFC原码的剖析,十分到位,特别是前面对于MFC六大关键技术的总结和演示程序,尤其精彩。那为什么我要说不要看这本书呢?   我是站在一个初学者的角度来说这句话的,也是我当初看了这本书的一些感受(因为过于难以理解,差了几章没有看,后来再补的),这本书对于MFC的讲解对一个初次接触MFC的人来说,内容过于的晦涩难懂,大段大段的原码引用,一

    2022年6月23日
    32
  • 表示一个ASCⅡ字符与一个汉字分别要使用几个字节_字,字节

    表示一个ASCⅡ字符与一个汉字分别要使用几个字节_字,字节“一个字等于多少个字节?”是一个不严谨的问法直接回答一个字等于多少个字节,也是不严谨的答法。相关概念:1、位(bit)来自英文bit,音译为“比特”,表示二进制位。位是计算机内部数据储存的最小单位。2、字节(byte)字节来自英文Byte,音译为“拜特”,习惯上用大写的“B”表示。字节是计算机中数据处理的基本单位。3、字(word)计算机进行数据处理时,一次存取、加工和…

    2022年10月1日
    3
  • python究竟要不要使用多线程

    (1)python多线程究竟有没有用?(2)python虚拟机机制如何控制代码的执行?(3)python中多进程处理原理是怎么样的?1.先来看两个例子(1)例1分别用单线程、使用多线程、使

    2021年12月29日
    47

发表回复

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

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