目录前言函数重载1.1 函数重载的概念1.2 函数重载的意义1.3 名字修饰(name Mangling)1.4 extern "C"前言 自然语言中,一个词可以
自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。
比如:以前有一个笑话,国有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”
函数重载:
//C语言不支持重载,C++支持重载
int Add(int left, int right)
{
return left+right;
}
double Add(double left, double right)
{
return left+right;
}
int Add(int left, double right)
{
return left+right;
}
int Add(double left, int right)
{
return left+right;
}
int main()
{
Add(10, 20);
Add(10.0, 20.0);
Add(10, 20.0);
Add(10.0, 20.0)
return 0;
}
下面两个函数属于函数重载吗?
short Add(short left, short right)
{
return left+right;
}
int Add(short left, short right)
{
return left+right;
}
int main()
{
Add(10, 20);
Add(10, 20);
return 0;
}
代码解析:
意义:
在C语言中,想要定义多个不同类型交换数据的子函数,需要不同的函数名来命名,比如SweapA、SweapB…等等
void SweapA(int *pa, int *pb)
{
int temp = *pa;
*pa = *pb;
*pb = temp;
}
void SweapB(double *pa, double *pb)
{
double temp = *pa;
*pa = *pb;
*pb = temp;
}
int main()
{
int a = 10, b = 20;
double c = 10.0, d = 20.0;
SweapA(&a, &b);
SweapB(&c), &d);
return 0;
}
void Sweap(int *pa, int *pb)
{
int temp = *pa;
*pa = *pb;
*pb = temp;
}
void Sweap(double *pa, double *pb)
{
double temp = *pa;
*pa = *pb;
*pb = temp;
}
int main()
{
int a = 10, b = 20;
double c = 10.0, d = 20.0;
Sweap(&a, &b);
Sweap(&c), &d);
return 0;
}
名字修饰(name Mangling):
为什么C++支持重载,而C语言不支持呢?
在linux下使用GCc和g++编译器演示函数名被修饰后的名字
采用C语言编译器编译后结果(反汇编)
结论:在Linux下,采用gcc编译完成后,函数名字的修饰没有发生改变
采用C++编译器编译后结果(反汇编)
结论:在Linux下,采用g++编译完成后,函数名字的修饰发生改变,编译器将函数参数类型信息添加到修改后的名字中
gcc的函数修饰后名字不变。而g++的函数修饰后变成(_Z+函数长度+函数名+类型首字母)
C语言没办法支持重载,因为同名函数没办法区分。而C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载
windows下名字修饰规则
结论:对比Linux会发现,windows下C++编译器对函数名字修饰非常奇怪,但道理都是一样的
扩展学习:C/C++函数调用约定和名字修饰规则
C++函数重载
C/C++的调用约定
接下来,再演示一个例子
f.h
#include <stdio.h>void f(int a, double b);
void f(double b, int a);f.cpp
#include "f.h"void f(int a, double b);
{
printf("%d %lf\n", a, b)
}void f(double b, int a);
{
printf("%lf %d\n", b, a)
}
Test.cpp
#include "f.h"int main()
{
f(1, 2.222);
f(2.222, 1);
return 0;
}
编译后,生成汇编指令;链接时,生成符号表
Linux下g++(C++)编译器的命名:
Linux下gcc(C)编译器的命名:
那么CPP是怎么调用C中的静态/动态库呢?(vs2022演示)
首先,我们用C来生成一个静态库或动态库
Test.h
#include <stdio.h>
void PrintArray(int* p, int n); //显示数组内容
void InsertSort(int* p, int n); //插入排序
Test.C
#include "Test.h"
void InsertSort(int* p, int n)
{
for (int i = 0; i < n - 1; ++i)
{
int end = i;
int tmp = p[end + 1];
while (end >= 0)
{
if (tmp < p[end])
{
p[end + 1] = p[end];
--end;
}
else
{
break;
}
}
p[end + 1] = tmp;
}
}
配置类型改成静态库后,生成解决方案,就得到后缀.lib文件了
在CPP项目中添加新的库目录(这个库是你生成的静态库的路径)
增加新的依赖项(依赖项为生成静态库的文件名+后缀"Test.lib")
做完这些准备后,我们来进行编译程序
extern "C"
{
//"../"是在当前目录的上一个目录中找文件
#include "../../Test/Test/Test.h"
}
#include <iOStream>
using namespace std;
void TestInsertSort()
{
int Array[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
InsertSort(Array, sizeof(Array) / sizeof(Array[0]));
for (int i = 0; i < 10; ++i)
cout << Array[i] << " ";
cout << " " << endl;
}
int main()
{
TestInsertSort();
return 0;
}
如果C想调用CPP的静态或动态库呢?
Test.h
#include <stdio.h>
#ifdef __cplusplus
#define EXTERN_C extern "C"
#else
#define EXTERN_C
#endif
EXTERN_C void PrintArray(int* p, int n);
EXTERN_C void InsertSort(int* p, int n);
Test.cpp
#include "Test.h"
void PrintArray(int* p, int n)
{
for (int i = 0; i < n; ++i)
{
printf("%d ", p[i]);
}
printf("\n");
}
void InsertSort(int* p, int n)
{
for (int i = 0; i < n - 1; ++i)
{
int end = i;
int tmp = p[end + 1];
while (end >= 0)
{
if (tmp < p[end])
{
p[end + 1] = p[end];
--end;
}
else
{
break;
}
}
p[end + 1] = tmp;
}
}
感谢大家支持!!!
到此这篇关于C++深入浅出讲解函数重载的文章就介绍到这了,更多相关C++函数重载内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: C++深入浅出讲解函数重载
本文链接: https://www.lsjlt.com/news/150235.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0