> 文章列表 > 缺省参数-函数重载

缺省参数-函数重载

缺省参数-函数重载

缺省参数

缺省参数是声明或定义函数时为函数的参数指定一个默认值

有什么用?

更加灵活的增加默认值,或者手动给一个初始值,解决了C语言#define给死一个值的缺陷,C语言无法做到缺省参数这么灵活

struct Stack
{int* a;int top;int capacity;
};//void StackInit(Stack* ps)
//{
//	ps->a = (int*)malloc(sizeof(int) * 4);
//	ps->capacity = 4;
//	ps->top = 0;
//}//如果一开始明确知道要开辟100个,那么需要扩容
//如何更灵活控制初始空间?利用缺省参数void StackInit(Stack* ps,int DefaultCapacity = 4)
{ps->a = (int*)malloc(sizeof(int) * DefaultCapacity);if (ps->a == NULL){perror("malloc fail");return;}ps->capacity = DefaultCapacity;ps->top = 0;
}int main()
{Stack st;StackInit(&st, 100);// 插入100个数据StackInit(&st);// 不知道要插入多少数据 StackInit(&st);-> StackInit(&st2, 4);return 0;
}

C喜欢玩的方式
#define DEFAULT_CAPACITY 100
void StackInit(struct Stack* pst)
{
pst->a = (int*)malloc(sizeof(int) * DEFAULT_CAPACITY);
if (pst->a == NULL)
{
perror(“malloc fail”);
return;
}

pst->top = 0;
pst->capacity = DEFAULT_CAPACITY;
}

使用注意

是否可以定义和声明同时出现?
否,不明确到底用哪个。

如果缺省单独出现在定义时,在编译时就会报错,编译时检查语法就会发现你少给了一个参数
缺省参数-函数重载

缺省参数-函数重载
所以需要再声明时给出缺省参数,定义不能给,定义不关心是否缺省
缺省参数-函数重载

缺省参数-函数重载
缺省参数-函数重载

函数重载

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

为什么C++支持函数重载,而C语言不支持函数重载呢?

编译链接过程

缺省参数-函数重载
反汇编发现调用函数的call和jump到对应的地址
然而编译期间 拿不到函数定义所在的地址 只有声明的地址,更像是只得到了一个承诺
链接时 符号表合并和重定位 找到定义(兑现承诺)
并且如果直接在.c文件中定义函数,那么就不需要链接步骤了,在编译阶段就可以拿到函数定义地址
缺省参数-函数重载

缺省参数-函数重载

两次函数地址不一样,因为调试了2次,懒得改上面的图了

缺省参数-函数重载
总体流程
缺省参数-函数重载

发现C++ 两个重载函数StackPush()具有不同的地址,是因为函数名修饰规则

函数名修饰规则

从g++角度看,链接时
c++的函数名修饰区分了重载函数,不论是StackPush还是func的重载都可以区分
修饰名的规则拿<_Z4funci>来看 — int func(int a)
_Z是前缀
4是函数名个数,i是int的缩写

另一个是<_Z4funcid> — int func(int a,double d)
也就是int 和 double的缩写

c++的函数名修饰把形参类型的缩写带进来了,与返回值无关
这也是为什么返回值不同不构成重载的原因

缺省参数-函数重载
缺省参数-函数重载

C为什么不支持

缺省参数-函数重载

C比较直接,上面两个蓝框里面的名字直接用的函数名,并没有C++的函数名修饰,所以如果有2个同名函数,就不确定是哪个,无论参数是否相同。
C不支持重载,再编译时 就报错,没法写2个同名函数,所以只用gcc来看一个函数调用时用的函数名
缺省参数-函数重载
可以看到直接使用func,无法区分同名函数,所以不支持重载

编译器把函数返回值也带进函数名修饰规则能否实现重载呢?

也是不行的。
缺省参数-函数重载
即使更改了函数名修饰规则,带入返回值,只是解决链接时找的问题
但是在编译时无法确定Func()调用哪一个函数,返回值在调用时无法体现

是不是所有函数都要链接

如果直接在.c文件中定义函数,那么就不需要链接步骤了,在编译阶段就可以拿到函数定义地址(直接兑现)

有问题的函数重载情况

情况一

 /*1、是否构成重载 -- 构成2、问题。无参调用存在歧义*/
void f()
{cout << "f()" << endl;
}void f(int a = 0)
{cout << "f(int a)" << endl;
}int main()
{f(); // “f”: 对重载函数的调用不明确return 0;
}

情况二

缺省参数-函数重载

int Func();
double Func();int main()
{Func(); // 调用歧义return 0;
}