函数部分

rand函数

函数原型 :int rand(void);
所需头文件 : <cstdlib>
功能和返回值 : 求出并返回一个伪随机数


srand函数

函数原型 :void srand(unsigned int seed);
参数:seed产生随机数的种子
所需头文件 : <cstdlib>
功能:为使rand()能产生一系列伪随机整数而设置起始点。使用1作为seed参数,可以重新初化rand()。


需要指出,若不使用种子seed,则会出现每次运行程序产生的随机数是固定不变的。故rand函数返回的是伪随机数

引用的概念

  • 引用(&)是标识符的别名;
  • 定义一个引用时,必须同时对它进行初始化,使它指向一个已存在的对象。
    例如:
1
2
3
4
int i, j;
int &ri = i; //定义int引用ri,并初始化为变量i的引用
j = 10;
ri = j; //相当于 i = j;
  • 一旦一个引用被初始化后,就不能改为指向其它对象。
    引用可以作为形参。

引用可以实现函数形参和实参之间的双向传递

例如下列程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include<iostream>
using namespace std;

void swap(int& a, int& b) //定义引用类型的形参
{
int t = a;
a = b;
b = t;
}

int main() {
int x = 5, y = 10;
cout<<"x = "<<x<<" y = "<<y<<endl;
swap(x, y);
cout<<"x = "<<x<<" y = "<<y<< endl;
return 0;
}

含有可变参数的函数

C++标准中主要提供了两个方法

  • 如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型;
  • 如果实参的类型不同,我们可以编写可变参数的模板(第9章)。

initializer_list

initializer_list是一种标准库类型,用于表示某种特定类型的值的数组,该类型定义在同名的头文件中。


initializer_list的使用方法

  • initializer_list是一个类模板(第9章详细介绍模板)
  • 使用模板时,我们需要在模板名字后面跟一对尖括号,括号内给出类型参数。例如:
1
2
initializer_list<string>  ls;  // initializer_list的元素类型是string
initializer_list<int> li; // initializer_list的元素类型是int
  • initializer_list比较特殊的一点是,其对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。
  • 含有initializer_list形参的函数也可以同时拥有其他形参

initializer_list使用举例

  • 在编写代码输出程序产生的错误信息时,最好统一用一个函数实现该功能,使得对所有错误的处理能够整齐划一。然而错误信息的种类不同,调用错误信息输出函数时传递的参数也会各不相同。
  • 使用initializer_list编写一个错误信息输出函数,使其可以作用于可变数量的形参。

内联函数

  • 声明时使用关键字 inline。
  • 编译时在调用处用函数体进行替换,节省了参数传递、控制转移等开销。
  • 注意:
    • 内联函数体内不能有循环语句和switch语句;
    • 内联函数的定义必须出现在内联函数第一次被调用之前;
    • 对内联函数不能进行异常接口声明。

应用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>

using namespace std;

const double PI = 3.14159265358979;

inline double calArea(double radius) //inline关键字
{

return PI * radius * radius;

}

int main()
{

double r = 3.0;

double area = calArea(r);

cout << area << endl;

return 0;

}

其实本质上就是省略了函数的调用与返回,类似于将函数体直接粘贴至调用处。


constexpr函数(不是很理解用法)

constexpr函数语法规定

  • constexpr修饰的函数在其所有参数都是constexpr时,一定返回constexpr;
  • 函数体中必须有且仅有一条return语句。

constexpr函数举例

  • constexpr int get_size() { return 20; }
  • constexpr int foo = get_size();
    //正确:foo是一个常量表达式

带默认参数值的函数

默认参数值的说明次序

  • 有默认参数的形参必须列在形参列表的最右,即默认参数值的右面不能有无默认值的参数;
  • 调用时实参与形参的结合次序是从左向右。
  • 例:
1
2
3
int add(int x, int y = 5, int z = 6);//正确
int add(int x = 1, int y = 5, int z);//错误
int add(int x = 1, int y, int z = 6);//错误

默认参数值与函数的调用位置

如果一个函数有原型声明,且原型声明在定义之前,则默认参数值应在函数原型声明中给出;如果只有函数的定义,或函数定义在前,则默认参数值可以函数定义中给出。
例如:

1
2
3
4
5
6
7
8
9
int add(int x = 5 ,int y = 6)//原型声明在前
int main()
{
add();
}
int add(int x,int y)
{
return x+y;//此处不能够再指定默认值
}
1
2
3
4
5
6
7
8
int add(int x = 5 ,int y = 6)//只有定义没有原型声明
{
return x+y;
}
int main()
{
add();
}

函数重载

C++允许功能相近的函数在相同的作用域内以相同函数名声明,从而形成重载。方便使用,便于记忆。

注意事项:

  • 重载函数的形参必须不同:个数不同或类型不同。
  • 编译程序将根据实参和形参的类型及个数的最佳匹配来选择调用哪一个函数。(编译器不以形参名和函数的返回值来区分)
  • 不要将不同功能的函数声明为重载函数,以免出现调用结果的误解、混淆。

重载函数应用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
int sumOfSquare(int a, int b) {
return a * a + b * b;
}
double sumOfSquare(double a, double b) {
return a * a + b * b;
}
int main() {
int m, n;
cout << "Enter two integer: ";
cin >> m >> n;
cout<<"Their sum of square: "<<sumOfSquare(m, n)<<endl;
double x, y;
cout << "Enter two real number: ";
cin >> x >> y;
cout<<"Their sum of square: "<<sumOfSquare(x, y)<<endl;
return 0;
}

运行结果:
Enter two integer: 3 5
Their sum of square: 34
Enter two real number: 2.3 5.8
Their sum of square: 38.93