c++入门(二)函数重载 --- c和c++中相互调用对方的静态库

c++入门(二)函数重载 --- c和c++中相互调用对方的静态库,第1张

目录

函数重载

定义

举例

函数

注意

 原因

c:

c++:

总结

创建一个C的静态库

将一个栈封装成一个静态库

c++调用c++库和c库

头文件包含

配置静态库 

原因

c++调用c++库

c++调用C库

c调用c库和c++库

创建cpp的栈的静态库

更改库的配置

c调用c库

c调用c++库

为什么还是链接不上呢?

怎么才能链接成功呢?

 原因

第一种

​ 第二种

​ 总结


函数重载 定义

是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。

举例

同名的函数,参数类型不同,那么构成重载函数,在c++中可以顺利运行

#include 
using namespace std;

int Add(int left, int right)
{
	return left + right;
}

double Add(double left, double right)
{
	return left + right;
}


int main()
{
	cout << Add(1,2) << endl;
	cout << Add(1.3, 2.4) << endl;
	return 0;
}

在c中运行失败:

 

函数
double compare(int,int)

重载函数有:

int compare(double,double)

double compare(double,double)

double compare(double,int)

double compare(int,double)

//……………………等等
注意

只与形参的类型,顺序,个数有关,与返回的类型无关,只要参数的类型、顺序、大小和原函数有所区别,那么返回类型可以任意,都构成重载函数。

若函数的参数类型,大小,顺序与原函数相同,但是返回类型不同,是不构成重载函数的

double compare(int,int)

int compare(int,int)

//不构成
 原因

在vs环境下不好区分,在Linux环境下编译区别

c:

c的编译器中,对函数的命名规则:

直接用我们给定的函数名进行编译

重载函数的函数名相同,编译时会发生访问冲突

c++:

c++的编译器中,对函数的命名规则:

_Z + 函数名长度 + 函数名 +参数类型的首字母

即使函数名相同,命名规则保证了编译时每个函数名的唯一性

访问不会发生冲突

总结

在c中,链接时,c中的函数名是直接以我们给的函数名确定的。

而在c++中,函数名的命名规则是_Z + 函数名长度 + 函数名 +参数类型的首字母

即使函数名相同的两个函数,只要符合重载条件,在c++中调用不会发生冲突。

因为函数名命名规则不同,c不支持函数重载。

无论在那个环境下,c++保证了重载函数函数名的唯一性。


创建一个C的静态库 将一个栈封装成一个静态库

将已经写好的栈的声明和定义在VS中打开,此时没有主函数,运行时编译器将项目当成一个可执行文件,进行运行,会报错,如下图:

接下来我们开始对此进行封装:

 完成后进行运行,如下图所示:

在此项目对应的文件下,就能找到封装的静态库:


c++调用c++库和c库 头文件包含

创建一个.cpp的项目,在主函数中用栈中的函数创建栈,初始化栈,销毁栈,如下图:

项目识别不了我们的 *** 作。

这里我们包含头文件必须要包含到栈的头文件才行,不在一个项目中,我们使用相对路径解决这个问题:

   

接下来我们包含头文件,要用到相对文件路径,直接在文件目录中找栈的头文件,从上图路径开始,向上一层,没有找到:

 再向上一层,找到关于栈的静态库文件:

 进入此路径下,找到此文件:

 进入此文件下,找到栈的头文件:

 包含头文件过程如下:

#include "../../Stack_C.lib/Stack_C.lib/Stack.h"

. . 是跳到上级目录,如上图,我们向上跳了两次,找到了静态库的文件,接下来就是正常的在路径下找头文件。包含头文件后,就可以识别对栈相关的 *** 作:

 运行一下,发现失败:

直接调用c库会失败,这里还需要进行配置 

配置静态库 

如下图 *** 作:

 点击编辑,进行如下图 *** 作:

效果如下:

之后,在静态库的文件下,在Debug下,找到静态库,将其文件名包括后缀都复制下来

 

 


再次运行:

 依旧是无法链接

原因

c库中函数的命名就是以我们给的函数名,而c++中的命名规则是_Z + 函数名长度 + 函数名 + 参数类型的首字母,进行完预编译,编译和汇编后,进行链接时,c++在c库中找不到对应的函数名,因此链接失败。

c++调用c++库

若我们将Stack.c改为Stack.cpp,运行一次,这样刚刚的c静态库,就会更新成c++的静态库

之后再运行test.cpp ,此时就是c++调用c++的静态库了

我们将Stack.cpp,改回来Stack.c,再次运行生成c的静态库

c++调用C库

那么我想要用c++来调用c的静态库怎么办? 

用到 entern"C",这是C++中的语法。

告诉编译器,用的是C库,用C的方式去链接,这样就可以链接成功。

extern "C"
{
#include "../../Stack_C.lib/Stack_C.lib/Stack.h"
}


c调用c库和c++库 创建cpp的栈的静态库

生成解决方案,在相对路径中可以找到该静态库

 创建新的.c源文件,对其头文件路径进行更改

更改库的配置

 此时库配置完毕。

c调用c库

此时,运行test.c,就是c调用c库

c调用c++库

 将Stack.c改回Stack.cpp,生成解决方案,静态库变回c++的静态库,运行test.c,就是c调用c++的静态库,如下:

为什么还是链接不上呢?

原因和c++直接调用c库链接不上的原因相同,c和c++库中,对函数的命名规则不同,c在c++的静态库中找不到对应的函数名,因此链接失败。

 有同学可能会说,在test.c中用 extern ,试试,这个语法是c++中的,不能在c中调用,想法不成立。

怎么才能链接成功呢?

既然 entern 是c++的语法,那么我们把entern "C",就用在 Stack.cpp 中,再生成解决方案,更新c++的静态库。

告诉编译器在c++的静态库中用C的方式去修饰这些函数。

如下:

 再次运行test.c :

 原因

头文件展开时,会将entern "C" ,放入test.c中,c识别不了这个语法,因此运行不通过。

但是思想是正确的,怎么样才能让 entern "C" 在 .cpp中出现,在.c中消失呢?

这里可以用条件编译来解决:

第一种

 第二种

 总结

更推荐第一种,直接用entern "C" ,包含所有函数,当函数很多时,更加高效!

c调用c++库,c++调用c库,都是在c++中做出调整,按c的规则对函数进行修饰!

链接失败的原因就是c++和c对函数的命名规则不同,这也是c++支持函数重载的原因!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/798347.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存