C++函数重载、隐藏与覆盖重写的精通指南

前言

对于C++函数而言,多个函数如果同名会有很多有意思的事情,从声明的作用域来看,在横向上同一个可访问作用域里面的同名函数可以进行重载;而纵向上作用域对于父子继承的派生类来说,同样的函数名称可以实现隐藏与覆盖。(如果基类成员函数是虚函数,可以基于虚函数实现多态,进行动态联编)下面就详细介绍下函数的重载、隐藏与覆盖重写。

1 函数重载

  • 定义:

C++规定在同一作用域中,例如一个类的成员函数之间,多个函数的名称相同,但是各个函数的形式参数(指参数的个数、类型或者顺序)不同时,构成函数重载。

  • 代码示例
int test(int a);
int test(int a, double b);
int test(double b, int a);
int test(int a, const char ** c);
void test(int a, const char ** c); 		  // 非重载,一起编译会提示错误,仅仅返回值不同编译无法区分使用的是那个重载函数
  • 总结
  • 前提:函数名称相同,即要求是同名函数;
  • 重载作用域:函数重载发生在横向水平的同一作用域,例如一个类成员函数之间的重载、全局函数之间的重载;
  • 重载类型:无论是类的静态成员函数,还是类的普通成员函数,亦或是普通的函数,都可以形成重载;
  • 重载要素:函数返回值类型函数重载无任何关系,仅仅返回值不同,形参相同的情况,会被禁止重载;

2 函数隐藏

  • 定义

函数隐藏是说,在不同作用域中,定义的同名函数构成函数隐藏(仅仅要求函数名称相同,对于返回值和形式参数不做更多要求,并且对于是否是虚函数也不做要求)。例如派生类同名成员函数屏蔽与其基类的同名成员函数,以及屏蔽同名全局外部函数。(经常有人隐藏和覆盖重写弄混,所以提前说下,如果在派生类中存在与基类同名的虚函数,并且返回值、形参都相同,则构成函数重写)。

  • 代码示例
#include <iostream>

using namespace std;

class Parent
{
  public:
    void test(int a) {
      cout<<"this is Parent"<<endl;
    }
};

class Son: public Parent
{
  public:
    void test(int a) {
      cout<<"this is Son hide Parent function"<<endl;
    }
};

int main(int argc, char ** argv) {
  Son son;
  son.test(1);
  return 0;
}

​ 输出如下

root@localhost override [master] $ g++ --std=c++11 test_hide.cpp
root@localhost override [master] $ ./a.out
this is Son hide Parent function
  • 总结
  • 前提:函数名称相同,即要求是同名函数;
  • 作用域:不在同一个横向的作用域(分别位于派生类与基类的纵向作用域);
  • 要素:返回类型可同可不同,参数亦可同可不同;
  • 虚函数:

    参数不同,此时无论有无virtual关键字,基类的函数将被隐藏;

    参数相同的情况下

    此时基类函数无virtual则属于函数隐藏,后续无法继续基于此利用这个函数的多态性;

    如果是virtual则属于函数重写,继续多态性的保留;

3 函数重写

  • 定义

函数的覆盖和重写是一个意思的两个叫法,同时他的作用域也和函数隐藏相同,其实可以这么看,函数覆盖和函数隐藏共同构建了在具有集成关系的纵向作用域里面的同名函数的不同衍变,只不过函数覆盖的条件更加严格些。

在介绍函数隐藏的时候,为了弄清楚函数隐藏与覆盖重写,也简单描述了函数覆盖。这里再进一步进行描述下:派生类中与基类中,同名函数的返回值类型、参数的都相同,并且基类中定义为虚函数的情况下,构成虚函数覆盖,也叫虚函数重写。

  • 代码示例
#include <iostream>
using namespace std;
class Parent
{
  public:
    virtual void test(int a) {
      cout<<"this is Parent"<<endl;
    }
};

class Son: public Parent
{
  public:
    void test(int a) {
      cout<<"this is Son Override Parent function"<<endl;
    }
};

int main(int argc, char ** argv) {
  Son son;
  son.test(1);
  return 0;
}

输出如下:

root@localhost override [master] $ g++ --std=c++11 test_override2.cpp
root@localhost override [master] $ ./a.out
this is Son Override Parent function

附:令人迷惑的隐藏规则

C++的隐藏规则使问题复杂性陡然增加,这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

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

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

总结

咋一看,感觉重写的功能基于隐藏是都可以实现,那么为什么要区分重写和隐藏呢?其实这是C++语言层面的问题了,C++基于virtual函数实现了多态性,并且可以进行动态联编,但是隐藏其实是破坏了这种多态性,也就是说父类成员函数的virtual性,在被子类成员函数的隐藏破坏后,无法传递给孙子类了,所以还需要重写来遗产的家族传递。

  • 前提:函数名称相同,即要求是同名函数;
  • 作用域:不在同一个横向的作用域(分别位于派生类与基类的纵向作用域);
  • 要素:返回类型可同可不同,参数亦可同可不同;
  • 是否虚函数:前提是虚函数,并且参数相同;

到此这篇关于C++函数重载、隐藏与覆盖重写的文章就介绍到这了,更多相关C++函数重载、隐藏与覆盖重写内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++函数重载介绍与原理详解

    目录 函数重载 函数重载的概念 函数重载的原理(名字修饰) 总结: extern “C” 函数重载 函数重载的概念 函数重载是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表必须不同.函数重载常用来处理实现功能类似,而数据类型不同的问题. #include <iostream> using namespace std; int Add(int x, int y) { return x + y; } double Add(double x, doub

  • 详解C++函数类型与重载函数

    目录 1. 2. 问题: 总结 1. 首先对重载函数,明确函数的返回类型不能决定重载函数的类别,即 int F(int ,int) ://一个返回 int 类型的函数 void F(int ,int)://一个无返回值的函数 //两者形参列表相同,返回值类型不同,但两者不构成重载函数 2. 注意形参列表中的默认值,使用含默认参数的重载函数时可能会产生二义性.例: int a = 0; int Max(int,int); int Max(int,int,int = 0); //则对Max(3,5)

  • C++中函数重载详解

    目录 函数重载的概念 函数重载的应用 为什么C++支持函数重载,而C语言不支持 函数重载的概念 函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的 形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题. 函数重载的应用 1.比如以下代码,函数名一样,而参数的类型不同,在调用的时候编译器会根据传递的参数自动进行匹配. 2.在例如以下代码,我们进行编译,都可以编译成功. 3.接下来看一个有趣的现象,将上述第二个例子

  • C++访问者模式模板函数无法重载的问题解决

    目录 背景 解决方案 最终代码 背景 最近遇到一个比较棘手的场景,我们有一堆模块,他们有一个通用的基类,我们不防假设为 BaseClass,该类有一些通用的结构以及需要重载的方法.这些模块有一个堆同名但是不同类型 参数的方法,比如: int DerivedClass1::DoNlpTask(const DerivedReq1& req, DerivedResp* resp); 类似这样的.每个 DerivedClass 的DoNlpTask都是同名不同参数的,而且这些要给业务去具体实现.正常来说

  • C++函数重载、隐藏与覆盖重写的精通指南

    前言 对于C++函数而言,多个函数如果同名会有很多有意思的事情,从声明的作用域来看,在横向上同一个可访问作用域里面的同名函数可以进行重载:而纵向上作用域对于父子继承的派生类来说,同样的函数名称可以实现隐藏与覆盖.(如果基类成员函数是虚函数,可以基于虚函数实现多态,进行动态联编)下面就详细介绍下函数的重载.隐藏与覆盖重写. 1 函数重载 定义: C++规定在同一作用域中,例如一个类的成员函数之间,多个函数的名称相同,但是各个函数的形式参数(指参数的个数.类型或者顺序)不同时,构成函数重载. 代码示

  • C++ 中函数重载、覆盖与隐藏详解

    C++ 中函数重载.覆盖与隐藏详解 在C++语言中,函数扮演着很重要的角色,不管面向过程设计,还是基于对象设计:不管是面向对象编程,还是基于泛型编程,函数都可以随处而见.在谈论C++中的函数重载.覆盖和隐藏之前,先回顾下函数的基础知识. 函数的声明包括函数的返回值类型,函数名称,参数列表(参数的类型.参数的个数.参数的顺序).例如,声明一个两个整数之和的函数,int iAdd(int iNum1,int iNum2);而函数的定义可以理解为对函数功能的详尽而准确的解说,通俗点,就是实现函数"ho

  • C++之重载 重定义与重写用法详解

    一.重载(重载函数) 重载函数是C++为了方便使用,允许在同一范围中(一个类中)声明几个功能类似的同名函数,但是这些同名函数的形参(指参数的个数.类型或者顺序至少有一个)必须不同 1.代码实现在一个类中fun()函数的重载: #include<iostream> using namespace std; class Base { public: void fun() { cout << "Base::fun()" << endl; } void fu

  • 通过实例理解javascript中没有函数重载的概念

    将函数名想象为指针,也有助于理解为什么ECMAScript中没有函数重载的概念.如下例子: 复制代码 代码如下: function addSomeNum(num) {     return num+100; } function addSomeNum(num) {     return num+200; } var result=addSomeNum(100);//300 显然,这个例子中声明了两个同名函数,而结果则是后面的函数覆盖了前面的函数.以上代码实际上与下面的代码是一致的. 复制代码 代

  • PHP和JAVA中的重载(overload)和覆盖(override) 介绍

    重载:同一个类中,函数名一样,返回值或者参数类型,个数不一样的叫做重载. 覆盖:同名函数,同返回值类型,同参数的叫做覆盖.指的是子类对父类中方法的覆盖. PHP不支持方法和操作符重载.JAVA不支持操作符的重载(但是"+"实际上是一种操作符重载). 复制代码 代码如下: <?php Class Father { public function fmeth1() { echo "fmeth1()...<br>"; } //public functio

  • PHP面向对象编程之深入理解方法重载与方法覆盖(多态)

    什么是多态? 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie Calverts对多态的描述--多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自"Delphi4编程技术内幕").简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针(没错这段话来自百度百科).那么多态的作用是什么,它有

  • 如何利用饰器实现 Python 函数重载

    目录 装饰器实现Python 函数重载 一.为什么 Python 中没有函数重载? 二.在 Python 中实现函数重载 三.把函数封装起来 四.构建虚拟的命名空间 五.使用装饰器作为钩子 六.从命名空间中找到正确的函数 七.实现函数的调用 八.运用函数重载 九.总结 装饰器实现Python 函数重载 函数重载指的是有多个同名的函数,但是它们的签名或实现却不同.当调用一个重载函数 fn 时,程序会检验传递给函数的实参/形参,并据此而调用相应的实现. int area(int length, in

  • JavaScript中的函数重载深入理解

    在JavaScript中有一种特殊的数据类型---Function类型,JavaScript的每个函数都是Function类型的实例.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定. <pre name="code" class="html">function sum(num1,num2) { return num1 +num2; } alert(sum(10,10)); //20 var other = sum; ale

  • 深度探究C++中的函数重载的用法

    C++ 允许同一范围内具有相同名称的多个函数的规范.这些函数称为重载函数,"重载"中对其进行了详细介绍.利用重载函数,程序员可以根据参数的类型和数量为函数提供不同的语义. 例如,采用字符串(或 char *)参数的 print 函数执行的任务与采用"双精度"类型的参数的函数执行的任务截然不同.重载允许通用命名并使程序员无需创建名称,例如 print_sz 或 print_d.下表显示了 C++ 使用函数声明的哪些部分来区分同一范围内具有相同名称的函数组. 重载注意事

  • Java方法覆盖重写实现原理解析

    这篇文章主要介绍了Java方法覆盖重写实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 方法覆盖重写注意事项: 1.必须保证方法名相同,返回值也相同 @Override:写在方法前面,用来检测方法的覆盖重写是否有效,这个注解不是必要的,就算不写,方法覆盖重写符合要求也是正确的 2.子类方法的返回值必须[小于等于]父类方法的返回值 3.子类方法的修饰符必须[大于等于]父类方法的修饰符 继承关系中,父子类构造方法的访问特点: 1.子类构造

随机推荐