C++学习8_函数重载与默认参数

函数重载

函数重载的意义

在实际开发中,有时候需要实现几个功能类似的函数,只是细节有所不同。

如交换两个变量的值,但这两种变量可以有多种类型,short, int, float等。

在C语言中,必须要设计出不同名的函数,其原型类似于:

void swap1(short *, short *);
void swap2(int *, int *);
void swap3(float *, float *);  

但在C++中,这完全没有必要。

C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数重载(Function Overloading)。

借助重载,一个函数名可以有多种用途。

函数重载的概念

函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重
载函数。

重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的
污染,对于程序的可读性有很大的好处。

C++进行函数重载的实现原理叫名字改编(name mangling),具体的规则是:

  1. 必须在同一作用域内。
  2. 函数名称必须相同 。
  3. 参数列表必须不同(参数的类型不同、个数不同、顺序不同)。
  4. 函数的返回类型可以相同也可以不相同。仅仅返回类型不同不足以成为函数的重载。

**注:**C++向下兼容C时,未做函数的名字改编。

若想要将一段代码用C语言的方式进行编译,可以用extern “C”{ }将其包起来,示例如下:

extern "C"
{
    int add(int x, int y){
        return x+y;
    }
}//end of extern c

若想要将一段代码,既可以放在C语言的编译器中,又可以放在C++的编译器中,均使用C语言的方式进行编译,可以用如下方式书写:

//如下表示:若为C++的编译器,则进入ifdef内部,使用extern C,若为C语言的编译器,则直接编译,不进入ifdef内部。
//C++与C的混合编程
#ifdef _cplusplus
extern "C"
{
#endif
    
    int add(int x, int y){
        return x+y;
    }
    
#ifdef _cplusplus
}//end of extern C
#endif

函数重载的原理

在编译生成目标文件(.o文件)时,对函数名字进行了改编。

在同一个作用域内,编译生成目标文件(.o文件)时,若函数名字相同,编译器会根据函数参数列表中的参数的类型、个数和顺序,对函数名进行改编。

0000000000000000 T _Z3  add i i   (add函数,参数为int和int类型)
0000000000000014 T _Z3  add i i i
    
0000000000000030 T _Z3  add  f f   (add函数,参数为float和float类型)
000000000000004a T _Z3  add  f f f  (add函数,参数为float、float和float类型)
0000000000000000 T _Z3  add  i i
0000000000000014 T _Z3  add  i i i

Linux常用命令

# 编译add.cc使其生成一个add.o文件
g++ -c add.cc

# 查看add.o文件的数据结构符号表
nm add.o

默认参数

默认参数的意义

减少代码书写量,减轻工作量。

C++可以给函数定义默认参数值。通常,调用函数时,要为函数的每个参数给定对应的实参。

void func1(int x, int y);
void func1(int x, int y)
{
cout << "x = " << x << endl;
cout << "y = " << y << endl;
}

无论何时调用func1函数,都必须要给其传递两个参数。但C++可以给参数定义默认值,如果将func1函
数参数中的x定义成默认值0, y定义成默认值0,只需简单的将函数声明改成

void func1(int x = 0, int y = 0);

这样调用时,若不给参数传递实参,则func1函数会按指定的默认值进行工作。允许函数设置默认参数
值,是为了让编程简单,让编译器做更多的检查错误工作。

默认参数的使用

  • 最好是在函数声明的时候就在参数列表里写上默认参数。
  • 当一个函数既有声明又有定义时,只需要在其中一个中设置默认值即可。
  • 如果函数声明时不写默认参数,而在函数定义时候写默认参数,那么调用函数就需要在函数定义了之后。若先调用后定义,在调用时编译器并不知道哪个参数设了默认值。

默认参数的顺序规定

如果一个函数中有多个默认参数,则形参分布中,默认参数应从右至左连续定义,否则会报错。

当调用函数时,只能向左匹配参数。如:

void func2(int a = 1, int b, int c = 0, int d);//error
void func2(int a, int b, int c = 0, int d = 0);//ok

若给某一参数设置了默认值,那么在参数表中其后所有的参数都必须也设置默认值,否则,由于函数调
用时可不列出已设置默认值的参数,编译器无法判断在调用时是否有参数遗漏。

默认参数与函数重载混合使用 可能造成二义性

默认参数可将一系列简单的重载函数合成为一个。例如:

void func3();
void func3(int x);
void func3(int x, int y);
//上面三个函数可以合成下面这一个
void func3(int x = 0, int y = 0);

如果一组重载函数(可能带有默认参数)都允许相同实参个数的调用,将会引起调用的二义性,使得编译时报错。
所以在函数重载时,要谨慎使用默认参数。

void func4(int);
void func4(int x, int y = 0);
void func4(int x = 0, int y = 0);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值