服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++函数重载、隐藏与覆盖重写的精通指南

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

2022-09-06 12:09秃顶的码农 C/C++

这篇文章主要给大家介绍了关于C++函数重载、隐藏与覆盖重写的相关资料,这几个名词看着好像很像,不过其实一样都不一样,本文通过实例代码介绍的非常详细,需要的朋友可以参考下

前言

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

1 函数重载

  • 定义:

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

  • 代码示例
?
1
2
3
4
5
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 函数隐藏

  • 定义

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

  • 代码示例
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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;
}

​ 输出如下

?
1
2
3
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 函数重写

  • 定义

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

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

  • 代码示例
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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;
}

输出如下:

?
1
2
3
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++函数重载、隐藏与覆盖重写内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7056331167099781150

延伸 · 阅读

精彩推荐
  • C/C++C++常见获取随机数的方法小结

    C++常见获取随机数的方法小结

    这篇文章主要介绍了C++常见获取随机数的方法,结合实例形式总结分析了C++获取随机数的几种常见方法与相关操作注意事项,需要的朋友可以参考下...

    Wayne-Zhu8982021-06-25
  • C/C++C++实现万年历源代码

    C++实现万年历源代码

    这篇文章主要介绍了C++实现万年历源代码,可以直接在VC6.0编译运行,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一...

    jxccy8885032021-08-26
  • C/C++C/C++根据年月日计算星期几(蔡勒公式篇)

    C/C++根据年月日计算星期几(蔡勒公式篇)

    这篇文章主要给大家介绍了关于C/C++根据年月日计算星期几(蔡勒公式篇)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一...

    AresKris10832021-10-26
  • C/C++C++指针与引用的异同

    C++指针与引用的异同

    这篇文章主要介绍了C++指针与引用的异同,文章以C++指针与引用的相关资料结合指针和引用的相同点和区别展开详细内容,需要的朋友可以参考一下...

    梁唐10372022-02-23
  • C/C++C++实现LeetCode(60.序列排序)

    C++实现LeetCode(60.序列排序)

    这篇文章主要介绍了C++实现LeetCode(60.序列排序),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    Grandyang5482021-11-29
  • C/C++C语言源码实现停车场管理系统

    C语言源码实现停车场管理系统

    这篇文章主要为大家详细介绍了C语言源码实现停车场管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    jqhsdtz5652021-08-11
  • C/C++c++传递函数指针和bind的示例

    c++传递函数指针和bind的示例

    这篇文章主要介绍了c++传递函数指针和bind的示例,需要的朋友可以参考下...

    C++教程网11382021-01-20
  • C/C++解析C++中的for循环以及基于范围的for语句使用

    解析C++中的for循环以及基于范围的for语句使用

    这篇文章主要介绍了解析C++中的for循环以及基于范围的for语句使用,是C++入门学习中的基础知识,需要的朋友可以参考下...

    C++教程网8892021-03-22