C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了extern "C" 与函数重载大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

如果向要在一个文件中使用另一个文件中的变量,不能在头文件中定义全局变量,因为被多个文件包含后会导致编译出错,并且静态的static变量,只能在本文件内使用,这时候就可以使用extern关键字。

extern 关键字:

  首先还是先看一下 extern 关键字的作用:extern关键字可以置于变量或函数前,以标示变量或函数的定义在别的文件中,提示编译器遇到此变量或函数时在其他模块中寻找其定义。

  通常情况下,比如我们在头文件  "b.h"  中声明了一个函数,然后在 "b.cpp" 中实现了该函数,当在 "main.cpp" 中调用 "b.h" 中声明的函数时,只需要在 ""main.cpp" 中 #include "b.h" 就可以了。例子如下:

@H_403_18@ 1 //b.h
@H_403_18@ 2 #ifndef _B_
@H_403_18@ 3 #define _B_
@H_403_18@ 4 
@H_403_18@ 5 #include<iostream>
@H_403_18@ 6 using namespace std;
@H_403_18@ 7 
@H_403_18@ 8 void test();
@H_403_18@ 9 
@H_403_18@10 #endif // _B_
@H_403_18@1 #include "b.h"
@H_403_18@2 void test()
@H_403_18@3 {
@H_403_18@4     cout << "test" << endl;
@H_403_18@5 }
@H_403_18@ 1 #include<iostream>
@H_403_18@ 2 #include"b.h"
@H_403_18@ 3 
@H_403_18@ 4 using namespace std;
@H_403_18@ 5 
@H_403_18@ 6 int main()
@H_403_18@ 7 {
@H_403_18@ 8     test();
@H_403_18@ 9     system("pause");
@H_403_18@10     return 0;
@H_403_18@11 }

除了通过 #include "b.h" 这样的方式能调用到 "b.h" 中的函数外,还有下面这种方式也能调用到"b.h" 的函数

@H_403_18@ 1 #include<iostream>
@H_403_18@ 2 //#include"b.h"  //在这里,不注释掉也是可以得,但是在对于 变量 来说时就必须注释掉了
@H_403_18@ 3 
@H_403_18@ 4 using namespace std;
@H_403_18@ 5 
@H_403_18@ 6 extern void test();    //告诉编译器test()函数声明在其他文件
@H_403_18@ 7 
@H_403_18@ 8 int main()
@H_403_18@ 9 {
@H_403_18@10     test();
@H_403_18@11     system("pause");
@H_403_18@12     return 0;
@H_403_18@13 }

上面是对于函数而言,那么要是在 "b.h" 中定义了一个全局变量 int x,(记住是全局变量哦!)现在我们想在 "main.cpp" 中访问变量 x,那该怎么办呢? 会不会 #include "b.h" 后就可以直接访问了呢?我们先试一下:

@H_403_18@ 1 //b.h
@H_403_18@ 2 #ifndef _B_
@H_403_18@ 3 #define _B_
@H_403_18@ 4 
@H_403_18@ 5 #include<iostream>
@H_403_18@ 6 using namespace std;
@H_403_18@ 7 
@H_403_18@ 8 int x = 10;
@H_403_18@ 9 
@H_403_18@10 void test();
@H_403_18@11 
@H_403_18@12 #endif // _B_
@H_403_18@1 //@H_21_16@main.cpp
@H_403_18@2 #include "b.h"
@H_403_18@3 
@H_403_18@4 int main()
@H_403_18@5 {
@H_403_18@6     cout << "x=" << x << endl;
@H_403_18@7     system("pause");
@H_403_18@8     return 0;
@H_403_18@9 }

我们在 "main.cpp" 中输出变量 x,在vs2017中会报错。  (上一个增量链接没有生成它;正在执行完全链接,error LNK2005: "int x" ([email protected]@3HA) 已经在 b.obj 中定义)

通过 #include "b.h" 这种方式就想访问到变量 x 太天真了,是访问不到的,因为 "b.h" 的全局变量 x 的访问作用域是文件作用域,它只能在 "b.h" 这个文件中进访问,记住是只能在 "b.h" 中进行访问,在 "b.cpp"中通过 #include "b.h" 你也是不能访问的。 那么现在我们有没有其他方式能在 "main.cpp" 中访问到变量 x 呢?当然有,通过 "extern" 关键字能达到目的。用法如下:

@H_403_18@ 1 //@H_21_16@main.cpp
@H_403_18@ 2 //#include "b.h"  //一定要注释掉
@H_403_18@ 3 #include <iostream>
@H_403_18@ 4 using namespace std;
@H_403_18@ 5 extern int x;
@H_403_18@ 6 
@H_403_18@ 7 int main()
@H_403_18@ 8 {
@H_403_18@ 9     cout << "x=" << x << endl;
@H_403_18@10     system("pause");
@H_403_18@11     return 0;
@H_403_18@12 }

说明:如果在一个文件中使用extren引入外部变量,在这文件修改这个变量,就等于修改了该外部变量。

说了那么多废话,终于把 extern 关键字说清楚了。接下来这个才是extern "C" 。

extern "C" 

  要说清楚 extern "C" 是怎么一回事,还得先说说C++函数重载的那些事。C++有函数重载,而C语言是没函数重载的。函数重载是指两个或多个函数之间函数名相同,参数列表不同,参数列表不同可以是参数的个数不同,或者是参数的个数相同但参数类型不同,需要注意的是如果函数名相同,参数列表完全相同但返回值类型不同是不能构成函数重载的。C++有函数重载是因为当生成obj中间文件/目标文件的时候,C++编译器把原函数名与参数信息结合,产生了一个独特的内部名字,比如有两个函数 void foo(int X) 和 void foo(void),最终产生的内部名字就是 _foo_int 和 _foo_void (实际产生的内部名字的命名规则应该不是这样的,这里我们并不关心它的命名规则是怎样的,只需要体会这个意思就可以了),通过这样编译器就能区分 void foo(int X) 和 void foo(void)这两个函数了。但是在C语言里面,并不会产生这样的内部名字,如果C语言里面有两个函数 void foo(int X) 和void foo(void),那么当生成obj中间文件/目标文件的时候,产生的名字就是 _foo 和 _foo 这样两个名字相同,C编译器就不能将两个函数区分开了,所以C语言里面也就没了函数重载。

  正是由于C++编译器 和 C编译器对函数名处理方式的不同,当我们的 C++ 程序调用 C 程序或者 C 程序调用 C++程序时就会存在问题。 有了问题那当然就得解决,于是就有了 extern "C" 的出现。

  所以说到底 extern "C" 的作用是用来解决名字匹配问题,实现 C 与 C++ 的混合编程。摆这么一句话在这里显得很苍白无力,还是举例说明一下。

 C++中函数重载,编译器的命名规则是

@H_403_18@ 1 int fun(int a,int b)
@H_403_18@ 2 {
@H_403_18@ 3     return a + b;
@H_403_18@ 4 }
@H_403_18@ 5 char fun(char a,char b)
@H_403_18@ 6 {
@H_403_18@ 7     return a + b;
@H_403_18@ 8 }
@H_403_18@ 9 
@H_403_18@10 void main()
@H_403_18@11 {
@H_403_18@12     cout<<fun(A,B)<<endl;
@H_403_18@13     cout<<fun(10,20)<<endl;
@H_403_18@14 }

 上述C++的两个重载函数被编译器命名为下:

 

extern "C" 与函数重载

extern "C" 与函数重载

extern "C" 与函数重载

在不同的平台的编译器中,命名规则不一定相同,其中的DDD和HHH代表返回值、第一个参数类型、第二个参数类型
如果再加一个参数
@H_403_18@1 int fun(int a,int b,char C)
@H_403_18@2 {
@H_403_18@3     return a + b;
@H_403_18@4 }

 命名会变为

 

extern "C" 与函数重载

extern "C" 与函数重载

可以得出,C++编译器的函数命名规则

而在C语言中,编译器将函数命名为

extern "C" 与函数重载

extern "C" 与函数重载

所以不论多少个函数,编译器都会命名为一样的函数,即使你的参数不一样,编译器也无法调动这个函数,所以就会报错
在C++中加extern “C” 
@H_403_18@ 1 extern "C" int fun(int a,int b)
@H_403_18@ 2 {
@H_403_18@ 3     return a + b;
@H_403_18@ 4 }
@H_403_18@ 5 extern "C" char fun(char a,20)<<endl;
@H_403_18@14 }

上述C++程序中,加一个extern "C"没问题,加两个就会报错了,加了extern "C"就等于用C语言的方式编译,函数的命名规则会变成C语言的,然而C语言不允许函数的重载。

在C++程序中调用被C编译器编译后的函数,加extern“C“声明,为了预防函数的重载出现。

函数重载的另一个问题

为什么返回值不能确定函数重载,如果有以下程序
@H_403_18@1 int fun(int a,int b)
@H_403_18@2 {
@H_403_18@3     return a + b;
@H_403_18@4 }
@H_403_18@5 char fun(int a,int b)
@H_403_18@6 {
@H_403_18@7     return a + b;
@H_403_18@8 }

 如果按照C++编译器的命名,这两个函数的命名也是不同的,为什么不能重载呢?

 

extern "C" 与函数重载

这时候并不是不行,而是调用一个函数,可以调用一个,也可以调用一个,然后编译器并不知道要调到哪个,出现了二义性,而不同的函数参数,在编译时就决定了调用哪个,编译器也不知道要将返回值给哪个类型,所以仅靠返回值是不能用来重载函数的。

 

[参https://www.cnblogs.com/418ks/p/6837669.html]

大佬总结

以上是大佬教程为你收集整理的extern "C" 与函数重载全部内容,希望文章能够帮你解决extern "C" 与函数重载所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。