C++手稿:函数与参数
2015-08-19 11:05
239 查看
默认参数
在函数声明中可以设置若干个默认参数,这些参数在函数调用时可以省略。例如:void print(int a = 3, int b=4){ cout<<a<<" "<<b<<endl; } print(); // 3 4 print(4); // 4 4 print(,3); // compile error
默认参数提供了更灵活的函数声明。简化函数逻辑的同时,也提供了一种扩展既有函数的方式。
在很多情况下,函数的声明与定义是分开的。语法上讲我们可以在声明时给出默认参数, 也可以在定义时给出默认参数。然而在函数调用处,编译器会进行语法检查, 被调用的“函数签名”是否存在、是否有歧义,只取决于调用处可见的那个函数(声明或定义)。
函数重载
我们知道可以通过参数个数的不同来进行函数重载。唯一需要注意的是重载函数调用的二义性。 通过参数个数进行重载的函数被调用时,便有可能存在歧义。例如:void print(int a = 1){} void print(int a = 1, int b = 2){} print();
同时定义上述两个
print()的调用存在歧义,此处会发生编译错误。
因此,使用默认参数时,要避免函数重载的二义性。
除了虚函数外,函数调用的函数地址是在编译期决定的。
可变参数
可变参数是指一个函数可以接受可变数目的参数,在C语言中最常见的便是printf和
scanf。
它们是如何实现的呢?
当然这不是函数重载,我们只定义一个函数,它可以接受任意个参数。
我们知道函数调用前需要将参数压栈,默认情况下C++会将参数从右向左顺序压栈。 栈空间是从高地址向低地址生长的,故第一个参数拥有最低的地址。 获取第一个参数后,我们只要知道后续参数的类型和个数,就可以逐个按照地址取出来。
在DLL生成和跨语言的过程调用时,常常遇到压栈顺序和由谁清空参数栈的问题,它们可以在函数声明中加入类似
_stdcall、
_cdecl等关键字来指定。
如何定义一个可变参数的函数?C++提供了stdarg.h头文件,它定义了若干宏来方便上述的操作。
首先使用
va_list来获取参数栈,
va_start来指定第一个参数的地址。
此后便可以使用
va_arg()来获取后续的参数了,这时需要指定类型(因为需要确定空间大小)。
最后用
va_end来释放资源。一个简单的可变参数的函数像这样:
#include <stdarg.h> void my_print(int count, ...){ va_list ap; va_start(ap, count); for(int j=0; j<count; j++) cout<<va_arg(ap, double)<<endl; va_end(ap); }
第一个参数是必不可少的,我们需要用它来确定参数的个数。
除非注明,本博客文章均为原创,转载请以链接形式标明本文地址: http://harttle.com/2015/07/07/cpp-functions-and-arguments.html
相关文章推荐
- C++手稿:指针与引用
- C++手稿:STL中的函数对象与函数指针
- C++手稿:STL入门
- C++与Java比较之向上转型
- c++标准库—命名空间std和头文件的演变
- 从更为底层的角度看C++
- C/C++程序员应聘常见面试题深入剖析
- 有关C/C++指针的经典面试题
- c语言面试题 指针30个常错题型
- C++输入字符串输入问题(二)
- C++的深拷贝与浅拷贝
- c语言-堆和栈的生长方向
- c语言-union联合体的使用
- C++学习之字符串的输入问题
- To new is C++; To malloc is C; To mix them is sin (混淆C++中的new和C中的malloc是一种犯罪)
- C++模板类详解
- To new is C++; To malloc is C; To mix them is sin (混淆C++中的new和C中的malloc是一种犯罪)
- (C/C++学习笔记)函数模板的深入理解
- Dijkstra算法 之 C语言详解
- C++标准库之IO库(一)