C++中函数重载的实现

来源:互联网 发布:qt多窗口编程 编辑:程序博客网 时间:2024/06/09 23:53

一、函数重载的概念:
通俗的讲:重载就是一个词有多种不同的含义。在C++程序中,将语义、功能相似的几个函数用同一个名字来表示,即为函数名重载。

二、函数重载的作用:
1、函数重载便于记忆,提高了函数的易用性。
2、类的构造函数需要重载机制,C++规定构造函数必须与类名相同。
3、使得各种运算符能够支持对象语义,因为C++中运算符的语义都是固定的,而且就那么几个运算符,所以要想让同一个运算符同时能支持对不同类型对象的操作就必须使用重载机制。

三、重载的实现
因为在最终的二进制可执行程序是不允许有同名函数出现的,所以作为语言实现的编译器必须为每一个被重载的函数生成唯一的内部变量。

1、如何实现函数重载?
答案是:根据参数列表为每个重载函数产生不同的内部标识符来实现。因为同名函数的参数不同,包括类型、顺序和数量不同,那么就很容易识别出它们是不同的函数。
【例】

#define _CRT_SECURE_NO_WARNINGS 1# include<iostream>using namespace std;//全缺省参数void Add1(int a = 0, int b = 0){    cout<< (a + b)<<endl;}//半缺省参数void Add2(int a, int b = 0){    cout<< (a + b)<<endl;}void test(){    Add1();    Add1(1);    Add1(1, 1);    Add2(2);    Add2(2, 2);}int main(){test();    system("pause");    return 0;}

运行结果:
这里写图片描述
释:
1)只要出现默认参数,那之后的参数也一定要带默认值。
2)默认参数在声明和定义中只能出现在一个地方。

2、函数重载需要注意的问题:
1)不能仅靠返回值类型的不同来区分重载函数。因为如果同名函数仅仅是返回值类型的不同,有时可以区分,有时却不能。
【例】

void Function(void); int Function(void); 

上述两个函数,第一个没有返回值,第二个返回值类型为int。当使用如下语句:
“int x = Function();”将存在歧义。

2)并不是两个函数名相同就能构成重载。如:全局函数和类的成员函数即使同名,也不算重载,因为它们的作用域不同。
【例】

void Print(...);//全局函数:文件作用域 class A{   ...   void Print(...);//成员函数,类作用域}

不论两个Print函数的参数是否相同,如果想调用全局的Print函数,都需要在函数前加一元作用域解析运算符“::”,否则成员函数将遮蔽同名的全局函数。
【例】

void A::Print(...)//类名(A)后加作用域解析符(::)再加函数名(Print),表调用的是成员函数,而不是全局函数{   ::Print(...);//表示调用的是全局函数,而不是成员函数} 

3)小心隐式类型转换导致重载函数产生二义性
【例】

# include<iostream>using namespace std;void output(int x);//函数声明void output(float x);//函数声明void output(int x){    cout << "output int " << x << endl;}void output(float x){    cout << "output float " << x << endl;}int main(){    int x = 1;    float y = 1.0;    output(x);//output int 1    output(y);//output float 1.0    output(1);//output int 1    //output(0.5);//error!不明确的调用,因为自动类型转换    output(int(0.5));//output int 0    output(float(0.5));//output float 0.5    system("pause");    return 0;}

运行结果为:
这里写图片描述
释:第一个output函数的参数为int类型,第二个output函数的参数是float类型。语句output(0.5)将产生编译错误,因为0.5的类型为double,而一个double临时变量既可以转换为int型,也可以转换为float型,二者都是标准转换。
注:隐式类型转换在很多地方可以简化程序的书写,但是也留下隐患。

3、C++程序如何调用已经被编译的C函数?
由于编译后的名字不同,C++程序不能直接调用编译后的C函数,需要加extern “c”来解决这个问题。
【例】

# ifdef _cplusplusextern “c”{#endifvoid _cdecl foo(int x, int y);...//其他函数#ifdef _cplusplus}#endif 

或者写成:

#ifdef _cplusplusextern “c”{#endif#include “myheader.h”...//其他C头文件#ifdef _cplusplus}#endif

因为C++标准并没有规定一种统一的重命名方案,因此不同的编译器对重载函数可能产生不同风格的内部标识符,这是不同产家的C++编译器和连接器不能兼容的重要原因。

四、解析面试题:
在C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明?
答:C++支持重载,而C语言不支持重载。函数被C++编译器编译和被C编译器编译后生成的内部名字是不同的,前者能显示到参数的类型,而后者不能。C++提供了C连接交换指定符号extern“C”来解决这个问题,即二进制兼容性问题。

原创粉丝点击