18 C++ - 函数重载(overload)

简介: 18 C++ - 函数重载(overload)

1. 函数重载概述

能使名字方便使用,是任何程序设计语言的一个重要特征!

我们现实生活中经常会碰到一些字在不同的场景下具有不同的意思,比如汉语中的多音字“重”。

当我们说: “他好重啊,我都背不动!”我们根据上下文意思,知道“重”在此时此地表示重量的意思。

如果我们说“你怎么写了那么多重复的代码? 维护性太差了!”这个地方我们知道,“重”表示重复的意思。

同样一个字在不同的场景下具有不同的含义。那么在c++中也有一种类似的现象出现,同一个函数名在不同场景下可以具有不同的含义。

在传统c语言中,函数名必须是唯一的,程序中不允许出现同名的函数。在c++中是允许出现同名的函数,这种现象称为函数重载。

函数重载的目的就是为了方便的使用函数名。

函数重载并不复杂,等大家学完就会明白什么时候需要用到他们,以及是如何编译,链接的。

2. 函数重载

2.1 函数重载基本语法

实现函数重载的条件:

  • 同一个作用域
  • 参数个数不同
  • 参数类型不同
  • 参数顺序不同
//1. 函数重载条件
namespace A{
  void MyFunc(){ cout << "无参数!" << endl; }
  void MyFunc(int a){ cout << "a: " << a << endl; }
  void MyFunc(string b){ cout << "b: " << b << endl; }
  void MyFunc(int a, string b){ cout << "a: " << a << " b:" << b << endl;}
    void MyFunc(string b, int a){cout << "a: " << a << " b:" << b << endl;}
}
//2.返回值不作为函数重载依据
namespace B{
  void MyFunc(string b, int a){}
  //int MyFunc(string b, int a){} //无法重载仅按返回值区分的函数
}

注意: 函数重载和默认参数一起使用,需要额外注意二义性问题的产生。

void MyFunc(string b){
  cout << "b: " << b << endl;
}
//函数重载碰上默认参数
void MyFunc(string b, int a = 10){
  cout << "a: " << a << " b:" << b << endl;
}
int main(){
  MyFunc("hello"); //这时,两个函数都能匹配调用,产生二义性
  return 0;
}

思考:为什么函数返回值不作为重载条件呢?

当编译器能从上下文中确定唯一的函数的时,如int ret = func(),这个当然是没有问题的。然而,我们在编写程序过程中可以忽略他的返回值。那么这个时候,一个函数为
void func(int x);另一个为int func(int x); 当我们直接调用func(10),这个时候编译器就不确定调用那个函数。所以在c++中禁止使用返回值作为重载的条件。

2.2 函数重载实现原理

编译器为了实现函数重载,也是默认为我们做了一些幕后的工作,编译器用不同的参数类型来修饰不同的函数名,比void func();编译器可能会将函数名修饰成_func,当编译器碰到void func(int x),编译器可能将函数名修饰为_func_int,当编译器碰到void func(int x,char c),编译器可能会将函数名修饰为_func_int_char我这里使用”可能”这个字眼是因为编译器如何修饰重载的函数名称并没有一个统一的标准,所以不同的编译器可能会产生不同的内部名。

void func(){}
void func(int x){}
void func(int x,char y){}

以上三个函数在linux下生成的编译之后的函数名为:

_Z4funcv //v 代表void,无参数
_Z4funci //i 代表参数为int类型
_Z4funcic //i 代表第一个参数为int类型,第二个参数为char类型

3. extern “C”浅析

以下在Linux下测试:

c函数: void MyFunc(){} ,被编译成函数: MyFunc

c++函数: void MyFunc(){},被编译成函数: _Z6Myfuncv

通过这个测试,由于c++中需要支持函数重载,所以c和c++中对同一个函数经过编译后生成的函数名是不相同的,这就导致了一个问题,如果在c++中调用一个使用c语言编写模块中的某个函数,那么c++是根据c++的名称修饰方式来查找并链接这个函数,那么就会发生链接错误,以上例,c++中调用MyFunc函数,在链接阶段会去找Z6Myfuncv,结果是没有找到的,因为这个MyFunc函数是c语言编写的,生成的符号是MyFunc。

那么如果我想在c++调用c的函数怎么办?

extern “C” 的主要作用就是为了实现c++代码能够调用其他c语言代码。加上extern "C"后,这部分代码编译器按c语言的方式进行编译和链接,而不是按c++的方式。

MyModule.h

#ifndef MYMODULE_H
#define MYMODULE_H
#include<stdio.h>
#if __cplusplus
extern "C"{
#endif
  void func1();
  int func2(int a,int b);
#if __cplusplus
}
#endif
#endif

MyModule.c

#include"MyModule.h"
void func1(){
  printf("hello world!");
}
int func2(int a, int b){
  return a + b;
}

TestExternC.cpp

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#if 0
  #ifdef __cplusplus
  extern "C" {
    #if 0
      void func1();
      int func2(int a, int b);
    #else
      #include"MyModule.h"
    #endif
  }
  #endif
#else
  extern "C" void func1();
  extern "C" int func2(int a, int b);
#endif
int main(){
  func1();
  cout << func2(10, 20) << endl;
  return EXIT_SUCCESS;
}
目录
相关文章
|
2月前
|
程序员 C++
C++中的函数重载有什么作用
【10月更文挑战第19天】C++中的函数重载有什么作用
24 3
|
6月前
|
编译器 C++
C++进阶之路:何为命名空间、缺省参数与函数重载
C++进阶之路:何为命名空间、缺省参数与函数重载
44 3
|
2月前
|
编译器 程序员 C++
C++中的函数重载是什么
【10月更文挑战第19天】C++中的函数重载是什么
35 0
|
7月前
|
存储 安全 编译器
【C++入门】缺省参数、函数重载与引用(下)
【C++入门】缺省参数、函数重载与引用
|
2月前
|
自然语言处理 编译器 Linux
【C++】巧用缺省参数与函数重载:提升编程效率的秘密武器
【C++】巧用缺省参数与函数重载:提升编程效率的秘密武器
|
4月前
|
编译器 程序员 C语言
C++函数重载
在实际开发中,有时候我们需要实现几个功能类似的函数,只是有些细节不同。例如希望交换两个变量的值,这两个变量有多种类型,可以是 int、float、char、bool 等,我们需要通过参数把变量的地址传入函数内部。在C语言中,程序员往往需要分别设计出三个不同名的函数,其函数原型与下面类似: void swap1(int *a, int *b); //交换 int 变量的值 void swap2(float *a, float *b); //交换 float 变量的值 void swap3(char *a, char *b); //交换 char 变量的
C++函数重载
|
2月前
|
程序员 C++ 开发者
C++入门教程:掌握函数重载、引用与内联函数的概念
通过上述介绍和实例,我们可以看到,函数重载提供了多态性;引用提高了函数调用的效率和便捷性;内联函数则在保证代码清晰的同时,提高了程序的运行效率。掌握这些概念,对于初学者来说是非常重要的,它们是提升C++编程技能的基石。
26 0
|
4月前
|
安全 编译器 C++
C++入门 | 函数重载、引用、内联函数
C++入门 | 函数重载、引用、内联函数
38 5
|
4月前
|
编译器 Linux C语言
【C++小知识】为什么C语言不支持函数重载,而C++支持
【C++小知识】为什么C语言不支持函数重载,而C++支持
|
5月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用