C++函数重载怎么定义使用

发布时间:2022-04-20 17:19:57 作者:zzz
来源:亿速云 阅读:150

这篇文章主要介绍了C++函数重载怎么定义使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C++函数重载怎么定义使用文章都会有所收获,下面我们一起来看看吧。

一、函数重载分析(上)

1.1 重载的定义

定义:同一个标识符在不同的上下文有不同的意义

1.2 函数重载的定义

如下:

C++函数重载怎么定义使用

下面看一段代码,感受一下:

#include <stdio.h>
#include <string.h>
int func(int x)
{
    return x;
}
int func(int a, int b)
{
    return a + b;
}
int func(const char* s)
{
    return strlen(s);
}
int main(int argc, char *argv[])
{
    printf("%d\n", func(3));
    printf("%d\n", func(4, 5));
    printf("%d\n", func("D.T.Software"));
    return 0;
}

下面为输出结果:

C++函数重载怎么定义使用

1.3 函数重载需要满足的条件

函数重载至少满足下面的一个条件:

下图所示就是参数的顺序不同:

C++函数重载怎么定义使用

下面看一个函数默认参数遇上函数重载的实例程序:

#include <stdio.h>
int func(int a, int b, int c = 0)
{
    return a * b * c;
}
int func(int a, int b)
{
    return a + b;
}
int main(int argc, char *argv[])
{
    int c = func(1, 2);
    return 0;
}

下面为输出结果:

C++函数重载怎么定义使用

编译报错,因为模棱两可。如果说调用第一个函数说的过去,因为符合函数默认参数规则,c 的值已经确定;调用第二个函数也符合常理,所以编译不会通过。

1.4 编译器调用重载函数的准则

将所有同名函数作为候选者

尝试寻找可行的候选函数

匹配失败

1.5 函数重载的注意事项

函数重载是由函数名和参数列表决定的!!!

函数重载的本质是什么?下面通过一段代码深入分析,编译环境为VS2012。

#include "stdafx.h"
#include <stdio.h>
int add(int a, int b)  // int(int, int)
{
    return a + b;
}
int add(int a, int b, int c) // int(int, int, int)
{
    return a + b + c;
}
int main()
{
    printf("%p\n", (int(*)(int, int))add);
    printf("%p\n", (int(*)(int, int, int))add);
    return 0;
}

由C语言的知识可以知道,函数名就是函数的入口地址,所以输出结果如下:

C++函数重载怎么定义使用

可以看到,两个 add() 函数的入口地址不一样,所以这两个 add 是两个不同的函数。

编译器是如何看待这两个 add() 函数的呢?下面来深入分析。先看一下编译器产生的中间结果,在Test -> Debug -> Test.obj 文件中。

C++函数重载怎么定义使用

C++函数重载怎么定义使用

C++函数重载怎么定义使用

然后使用VS2012里面自带的命令行工具查看 Test.obj 里面有什么东西。

C++函数重载怎么定义使用

上图示为VS2012 命令行所在位置

输入 dumpbin,如下:

C++函数重载怎么定义使用

这里只需要关系 SYMBOLS(符号表),符号表就是编译器在编译过程中根据源代码所生成的一张表,这张表有程序的函数名变量等等。

输入以下命令,其中 /symbols 后面为 Test.obj 所在的位置。

C++函数重载怎么定义使用

找到下面的地方,可以看到编译器编译 (int __cdecl add(int,int)) 时标识符为?add@@YAHHH@Z;而编译器编译(int __cdecl add(int,int,int)) 时标识符为?add@@YAHHHH@Z ,也就是说编译器在编译这两个函数时已经把这两个函数分别对待,尽管它们名字一样,所以两个 add() 函数的入口地址不一样,这就很好理解了。

C++函数重载怎么定义使用

1.6 小结

二、函数重载分析(下)

2.1 函数重载遇上函数指针

将重载函数名赋值给函数指针时

下面看一段代码:

#include <stdio.h>
#include <string.h>
int func(int x)
{
    return x;
}
int func(int a, int b)
{
    return a + b;
}
int func(const char* s)
{
    return strlen(s);
}
typedef int(*PFUNC)(int a);
int main(int argc, char *argv[])
{
    int c = 0;
    PFUNC p = func;
    c = p(1);   
    printf("c = %d\n", c);
    return 0;
}

下面为输出结果:

C++函数重载怎么定义使用

这也就是前面说的通过函数指针所指向的函数类型参数列表来进行选择。

注意事项

如下,这段代码想通过函数名获取重载函数的入口地址:

#include <stdio.h>
int add(int a, int b)  // int(int, int)
{
    return a + b;
}
int add(int a, int b, int c) // int(int, int, int)
{
    return a + b + c;
}
int main()
{
    printf("%p\n", add);
    printf("%p\n", add);
    return 0;
}

编译的时候会报错,无法确定是哪个函数。

C++函数重载怎么定义使用

2.2 C++和C的相互调用

如下:

C++函数重载怎么定义使用

在 Linux环境下新建一个 9-2 文件夹,先在文件夹下新建 add.c 和 add.h 文件,如下:

add.c :

#include "add.h"
int add(int a, int b)
{
    return a + b;
}

add.h :

int add(int a, int b);

通过 linux 命令 cd 进入 9-2 文件夹,再将 add.c 转换成 add.o 文件,如下所示:

C++函数重载怎么定义使用

然后在 9-2 文件夹下建一个 main.cpp 文件,如下:

C++函数重载怎么定义使用

mian.cpp :

#include <stdio.h>
#include "add.h"
int main()
{
    int c = add(1,2);
    printf("c = %d\n", c);
    return 0;
}

对程序进行编译,发现程序报错,没有定义 add() 函数,但是函数确实已经定义了,可以使用 linux 中的 nm 指令查看 add.o 里面的信息,打印出来的就是符号表信息,可以看到确实有 add 。

C++函数重载怎么定义使用

这个时候就需要使用 extern关键字强制让C++编译器进行C方式的编译,所以 main.cpp就要修改成这样:

#include <stdio.h>
extern "C"
{
  #include "add.h"  
}
int main()
{
    int c = add(1,2);
    printf("c = %d\n", c);
    return 0;
}

这样编译就能通过了:

C++函数重载怎么定义使用

如果在 9-2 文件中新建一个 main.c 文件,main.c 里面的代码 与 main.cpp 中的相同。

C++函数重载怎么定义使用

进行编译,发现会报错误,因为 extern 关键词写法是 C++ 中的, C语言不支持该写法。那有没有一种写法既能被 C语言编译通过,又能让 C++编译通过呢?且看下面。

2.3 使得C代码只会以C的方式被编译的解决方案

如下:

C++函数重载怎么定义使用

所以上述代码可以写作,main.c和 main.cpp 均为:

#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "add.h"
#ifdef __cplusplus
}
#endif
int main()
{
    int c = add(1, 2);
    printf("c = %d\n", c);
    return 0;
}

这样程序在 C语言和 C++ 的编译环境下均能通过,如下:

C++函数重载怎么定义使用

注意事项

C++编译器不能以C的方式编译重载函数

编译方式决定函数名被编译后的目标名

下面通过一个例子说明一下:

int add(int a, int b)  // int(int, int)
{
    return a + b;
}
int add(int a, int b, int c) // int(int, int, int)
{
    return a + b + c;
}

将该代码编译成目标文件,取名为 test.oo,然后通过 linux 中的 nm 命令查看 test.oo 中的东西,可以看到 test 符号表里面有两个东西 T _Z3addii 和T _Z3addiii,这就是 add 函数被编译过后的目标函数名,ii 表示两个参数, iii 表示三个参数。

C++函数重载怎么定义使用

如果采用 C 方式编译重载函数,代码如下:

extern "C"
{
    int add(int a, int b)  // ==>add
    {
        return a + b;
    }
    int add(int a, int b, int c) // ==>add
    {
        return a + b + c;
    }
}

下面为编译结果,可以看到编译报错,说两个 add() 函数冲突了。

C++函数重载怎么定义使用

关于“C++函数重载怎么定义使用”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“C++函数重载怎么定义使用”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. c++中怎么判断函数重载
  2. 如何在C++中使用const实现函数重载

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++

上一篇:Python怎么绘制百分比堆叠柱状图并填充图案

下一篇:Oracle sysaux表空间异常增长怎么解决

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》