C++初阶之函数重载

目录

1.函数重载

1.1 概念

1.2 C++支持函数重载的原因

2.extern “C”

2.1 C++调用C语言写的静态库

2.2 C调用C++写的静态库

        在自然语言中,一个词可以有多种意思,人们可以通过联系上下文来判断这个词的真正意思,放在编程语言中,就可以称这个词被重载了

1.函数重载

1.1 概念

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

        举个栗子:

//参数类型不同

int ADD(int a, int b)
{
    return a+b;
}

double ADD(double a, double b)
{
    return a+b;
}

//参数顺序不同

void func(int a, double b)
{
    cout << "int func(int a, double b)" << endl;
}

void func(double a, int  b)
{
    cout << "int func(double a, int b)" << endl;
}

//参数个数不同

void test()
{
    cout << "void test()" << endl;
}

void test(int a)
{
    cout << "void test(int a)" << endl;    
}

1.2 C++支持函数重载的原因

        C语言是不支持函数重载的,这是为啥呢?

        在程序运行过程中,要经历预处理,编译,汇编,链接四个步骤,源文件通过前三步生成目标文件,但是编译时独立的,在编译结束生成的目标文件中,在调用函数的地方就会换成经过修饰的函数名,相应的也就有符号表——C语言和C++的名字修饰规则不同,这也是为什么C++支持函数重载而C语言不支持的关键所在。在链接的过程中,编译器自己会在符号表中找相对应的函数名,进而找到地址进行链接,完成程序的运行,此时,C语言的名字修饰规则会使重名的函数无法区分,编译器分别不了,就会出现连接错误

        以下是在Linux系统中编写的C语言程序,以及生成的函数符号

 我们可以清楚地看到,在Linux环境下,C语言程序的函数名字修饰规则就是直接取函数名,那么必然函数重名会使得编译器分别不了,所以C语言不支持函数重载

        以下是在Linux系统中编写的C++程序,以及生成的函数符号

 对比着C语言程序生成地函数符号,我们可以清楚地看到C++的名字修饰是将参数的类型也放了进去,这样使得即使函数重名,但是参数不同时,生成的符号名也不同,这样编译器在寻找的时候就不会出现C语言中分不清的情况了

        上面展示的是在Linux环境下C语言与C++的名字修饰规则,Windows环境下相较要麻烦许多,想要了解的朋友可以自行百度,这里我就不再赘述了

注意:

  • 如果两个函数函数名和参数是一样的,返回值不同是不构成重载的,因为调用时编译器没办法区分

2.extern “C”

        我们都知道C++是兼容C语言的,那么C语言程序能否调用C++写的库呢?C++程序又能否调用C语言写的程序呢?回答是肯定的,但是需要借助extern “C”来完成

2.1 C++调用C语言写的静态库

        首先生成C语言写的静态库,我们将C语言实现的Stack程序生成静态库,如果我们直接编译程序,会出现下图所示错误(因为我们没写主函数)

         此时编译器默认生成.exe文件,但我们需要的是.lib的文件,按照下图的操作进行处理,可生成静态库

        完成修改后重新生成解决方案,就可以得到C语言写的静态库了,如下图

         此时我们重开一个项目,用C++程序来调用这个库,发现编译报错,我们知道如果要用相应的函数需要包含相应的头文件,但是编译后还是会出现错误,如下两图

         编译器默认到当前文件路径去找相应的文件,而我们的静态库文件不在此处,我们可以使用相对路径或者绝对路径去找目标头文件,我在这就使用绝对路径了

         此时我们重新编译发现还是不对,我们还需要进行处理,如下两图

         完成上面的步骤进行重新生成解决方案,发现编译链接都没问题了,但是找不着函数名,这是因为我们使用的是C语言所写的库,使用的名字修饰规则是C语言的,C++不认识,此时,extern就上场了~

         上面的语句是向编译器说明,这个库是用的C语言的名字修饰,因为C++兼容C语言,那么C++肯定知道C语言的名字修饰规则,就在执行的时候按照C语言的规则来了,这样程序就能跑起来了~

2.2 C调用C++写的静态库

        前面的步骤和C++调用C语言写的静态库一样,先生成C++的静态库,再重开一个程序,用C的程序去调用C++写的静态库

        但是,extern “C”是C++的语法,C语言编译器是不认识的,所以我们不能在调用C++静态库的C语言程序中做文章,而是应该在C++所写的静态库中做文章,我们的目的是让函数在编译的时候按照C语言的名字修饰规则生成函数的符号表,我们想当然的就会在函数声明出直接加extern,如下图

         当我们重新生成静态库,再去调用时,会发现还是不行,这是为什么呢?

        因为我们引用的头文件会在被引用处直接展开,那么也就是说上图显示的代码会直接展开在C语言的程序中,问题又回来了,C语言是不认识extern的,那该怎么解决这个问题呢?

        使用条件编译可以很好的解决这个问题,如下图

         然后再重新生成解决方案,就可以实现C语言程序调用C++写的静态库了~

以上就是本篇博客的全部内容了~

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值