1、数组形参
void fun(const int* beginptr, const int* endptr)
{
while (beginptr != endptr)
cout << *beginptr++ << " ";
cout << endl;
}
int a[3]; //全局数组 默认初始化
void test()
{
int b[3]; //不会初始化
int c[3] = {}; //会初始化
int d[3] = {1}; //会初始化
fun(begin(a), end(a));
fun(begin(b), end(b));
fun(begin(c), end(c));
fun(begin(d), end(d));
}
输出(即使b未初始化 也是输出三个值)
0 0 0
-858993460 -858993460 -858993460
0 0 0
1 0 0
另外c++允许将变量定义为数组的引用,因此形参也可以是数组的引用
void fun(const int (&arr)[3])
{
for (auto e : arr)
cout << e << endl;
}
void test()
{
int a[3] = {};
int b[4] = {1};
fun(a); //正确
fun(b); //错误 长度不一致
}
2、返回类型和return语句
函数的返回类型决定函数的调用是否是左值,调用一个返回引用类型的函数,得到的是左值,其他返回类型是右值。
3、编写一个函数声明,使其返回数组的引用并且该数组包含10个string
对象。
string(&fun())[10];
//使用类型别名
typedef string arr[10];
arr& fun();
//使用尾置返回类型
auto fun()->string(&)[10];
//使用decltype关键字
string s[10];
decltype(s)& fun();
4、函数重载和const形参
顶层const不影响传入函数的对象。一个拥有顶层const的形参无法和另一个没有顶层const的形参区分开来
int fun(int a) { return 1; }
int fun(const int a) { return 2; }// 重复声明int fun(int a)
int fun(int* a) { return 3; }
int fun(int* const a) { return 4; }// 重复声明int fun(int* a)
再看下面的几个重载
int fun(int& a) { return 5; }
int fun(const int& a) { return 6; }
int fun(int* a) { return 7; }
int fun(const int* a) { return 8; }
void test()
{
int a = 3;
cout << fun(a) << endl; //5
cout << fun(1) << endl; //6
}
5、重载与作用域
在内层作用域中声明的名字将隐藏外层作用域中声明的同名实体(只在乎是否同名,不在乎参数)。在不同作用域中无法重载函数名。
string read();
void print(const string&);
void print(double);
void test()
{
bool read = false; //隐藏了外层的read
string s = read();//错误:外层的read被隐藏,现在的read只是个bool变量
void print(int);
print("abs"); //错误:外层的print都被隐藏,现在的print只接收一个int参数
print(3.14); //正确:外层的print都被隐藏 调用print(int)
}
6、函数匹配
首先编译器会从同名重载函数中寻找可行函数,再从可行函数中寻找最佳匹配函数,最佳匹配函数满足下列条件之一,且有且只有一个这样的函数
1)该函数每个实参的匹配都不劣于其他可行函数
2)至少有一个实参的匹配优于其他可行函数体哦那个的匹配
入无法找到这样的函数编译器将报告二义性调用的信息。
void f() { cout << 1 << endl; }
void f(int) { cout << 2 << endl; }
void f(int, int) { cout << 3 << endl; }
void f(double, double = 1.2) { cout << 4 << endl; }
void test()
{
f(3.14); //调用第4个函数
f(1, 3.14);//无法找到最佳匹配函数,编译失败 二义性
}