C++PrimerPlus 学习笔记 | 第八章 函数探幽 |3.默认参数 & 4.函数重载

默认参数

默认参数是指当函数调用的时候省略了实参自动使用的一个值.

// 函数原型
void wow(int n = 1);
// 如果这样调用函数等价于 wow(1)
wow() // == wow(1)

对于带有参数列表的函数,必须从右向左添加默认值,也就是说,要为某个参数设置默认值,则必须为他右边的所有参数提供默认值。

实参按从左往右的顺序依次被赋给相应的形参,不能跳过任何参数,也就是说如果要使用某项参数的默认值,则所有在其右边的参数都必须为默认值.

以下的原型和调用都是非法的

// 函数原型
int wow(int a,int b = 0,int c); // 提供默认参数的形式参数右边都必须提供默认参数

// 函数调用
int owo(int a,int b = 0,int c = 0); // 这个是合法的函数原型
owo(1); // 合法 等价于 owo(1,0,0);
owo(1,,1); // 非法,如果要使用某项形式参数的默认值则在其右边的参数也必须是默认值,该调用可以改写如下
owo(1,0,1); // 该调用是上述的合法形式

函数重载

函数多态是C++在C语言的基础上新增的功能,默认参数能让您能够使用不同数目的参数调用一个函数。而函数多态(函数重载)允许您创建多个同名函数。术语多态是指有多种形式,因此术语函数多态允许函数可以有多种形式,类似的术语函数重载允许有多个同名函数,对其名称进行了重载。这两个术语指的同一件事。但我们通常使用函数重载,可以通过函数重载来设计一系列函数,他们完成相同的功能,但使用不同的参数列表

函数多态和函数重载的区别关键点:

函数重载是静态绑定,编译阶段实现

函数多态是动态绑定,运行阶段实现

https://www.cnblogs.com/devilmaycry812839668/p/6362082.html

函数重载的关键是参数列表,也称为函数特征标(function signature 似乎函数签名会更好听?),如果两个函数参数数目和类型相同且排列顺序也相同,则他们的特征标(签名)相同,变量名是无关紧要的。C++允许定义相同名称的函数但条件是特征标不同。

注意:如果函数名不同则两个函数一定不会相同,在函数名相同的情况则特征标一定要有区别,注意返回值不足以区分函数

看一下的函数重载实例

// 函数原型
void print(const char * str, int width);
void print(double d, int width);
void print(long l,int width);
void print(int i, int width);
void print(const char * str);

// 函数调用
print("Llonvne", 5); // #1
print(123.12,3); // #2
print(1234L,4); // #3
print(1234,4); // #4
print("Lcosvle"); //#5

在函数重载的时候,需要在调用函数的时候提供正确的参数类型,对于以下语句不会通过编译

unsigned int year = 3210;
print(year, 4); // ambiguous call 模凌两可的函数调用

但是如果省去函数原型#2,#3反而能够通过编译,为什么呢,因为如果删去2,3就只剩下一个原型将数字视为第一个参数,C++会尝试将其转换为int型进行调用,但是现在存在三个原型将数字视为第一个参数,C++编译器该转换哪个去调用呢?编译器并不知道,C++将拒绝这种函数调用,将其视为一种错误!(三个和尚没水喝?)

一些看起来彼此不同的特征标是无法共存的,请看如下两个原型

double cube(double x);
double cube(double & x);

对于这种请注意C++编译器在编译调用函数的时候,只会查看函数原型,而不去查看函数具体实现,类似于上述两种函数C++编译器根本无法在编译的时候确定该调用哪个函数。

const变量与非const变量

// 函数原型
void dribble(char * bits); //overload;
void dribble(const char * cbits); //overload;
void dabble(char * bits); // not overloaded
void drivel(const char * bits); // not overloaded
// 函数调用
const char p1[20] = "How's the weather?";
char p2[20] = "How's the business?";
dribble(p1); // p1 is const char * -> void dribble(const char * cbits);
dribble(p2); // p2 is char * -> void dribble(char * bits);
dabble(p1); // 这将不会通过编译因为const char * 不符合 void dabble(char * bits); 丢失了const修饰符
dabble(p2); // 符合 void dabble(char * bits);
drivel(p1); // void drivel(const char * bits);
drivel(p2); // void drivel(const char * bits);
// const 参数也是接受const和非const参数,而非const参数只能接受非const参数

在函数名和函数特征标相同,则函数一定相同,函数返回值类型不能区别函数

以下代码将不能通过编译

int square(int x);
long square(int x);

重载引用参数

// 函数原型
void stove(double & r1);
void stove(consr double & r2);
void stove(double && r3);
// 函数调用
double x = 55.5;
consr double y = 32.0;
stove(x); // -> void stove(double & r1);
stove(y); // -> void stove(consr double & r2);
stove(x + y); // -> void stove(double && r3);
// 如果未定义右值引用,则函数将会调用 void stove(consr double & r2); 并创建临时变量,详见上文引用

何时使用函数重载

虽然函数重载很吸引人,但是也不要乱用。仅当函数基本执行相同的任务,但使用不同形式的数据的时候才使用函数重载

函数重载的秘密:名称修饰:C++如何跟踪重载函数,他给这些函数制定了秘密身份,使用C++编译器编译函数的时候,他会使用一些神奇操作----名称修饰。他根据函数原型种植钉的形参类型和顺序进行加密

// 函数名称
void print(double a);
void print(int a);
// 内部标识
__Z5printd 
__Z5printi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值