函数 Function 如何重用代码 How to reuse code
3 4 = 3*3*3*3
3 4,6 5 : 拷贝 - 粘帖代码 (Copy-paste code)
3 4,6 5,12 10 : 拷贝 - 粘帖代码 (Copy-paste code) Bad!
使用函数 (with a function)
使用函数 (with a function)
使用函数 (with a function) good!
为什么定义自己的函数? 可读性 :sqrt(5) 比粘帖一段计算平方根的代码更清楚! 可维护性 : 改变一个算法, 只需要修改这个算法的函数 ( 相比修改每一处代码 ) 代码重用 : 其他人可以使用你实现的算法!
函数定义语法 函数名 intraisetopower ( int base, int exponent) { int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; } return result; }
函数定义语法 返回类型 int raisetopower ( int base, int exponent) { int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; } return result; }
函数定义语法 参数 1 intraisetopower ( int base, int exponent) { int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; } return result; }
函数定义语法 参数 2 intraisetopower ( int base, int exponent) { int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; } return result; }
函数定义语法 参数列表 intraisetopower ( int base, int exponent) { int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; } return result; } 参数是有次序的 :
函数定义语法 函数签名 int raisetopower ( int base, int exponent) { int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; } return result; }
函数定义语法 int raisetopower ( int base, int exponent) { int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; } return result; } 函数体
函数定义语法 intraisetopower ( int base, int exponent) { } } int result = 1; for( inti = 1; i< exponent ; i++){ result = result*base; return result; 返回语句 : 返回与返回类型相同的值
函数调用 函数定义 intraisetopower( int base, int exponent){ int result = 1; for( inti= 1; i< exponent ; i++){ result = result*base; } return result; } 函数调用 intmain() { intthreeexpfour = raisetopower(3, 4) ; cout << "3^4 is " << threeexpfour << endl; return 0; }
返回值 最多只能返回一个值, 其类型需与返回类型一致.
返回值 最多只能返回一个值, 其类型需与返回类型一致. 如果没有返回值, 则函数返回类型为 void 类型
返回值 最多只能返回一个值, 其类型需与返回类型一致. 如果没有返回值, 则函数返回类型为 void 类型 - 注意 : 不能声明 / 定义一个 void 类型的变量!
返回值 return 语句不一定在函数的最后. 只要执行一个 return 语句, 函数执行就结束了!
实参与形参类型要一致 函数定义的参数列表中变量称为形式参数 ( 简称形参 ); 而函数调用时传给函数的参数叫做实际参数 ( 实参 ) 实参的类型要和对应的形参类型一致 ( 或能转化为形参类型 ).
实参与形参类型要一致 函数定义的参数列表中变量称为形式参数 ( 简称形参 ); 而函数调用时传给函数的参数叫做实际参数 ( 实参 ) 实参的类型要和对应的形参类型一致 ( 或能转化为形参类型 ).
实参与形参类型要一致 函数定义的参数列表中变量称为形式参数 ( 简称形参 ); 而函数调用时传给函数的参数叫做实际参数 ( 实参 ) 实参的类型要和对应的形参类型一致 ( 或能转化为形参类型 ).
函数重载 许多函数可以有相同的名字, 但不同的参数 调用时, 根据参数匹配确定调用哪个函数
函数重载
函数重载
函数声明必须在函数被调用之前
函数声明必须在函数被调用之前 - 解决方法 1: 改变函数声明次序
函数声明必须在函数被调用之前 - 解决方法 1: 改变函数声明次序 - 解决方法 2: 使用一个函数原型 (function prototype), 通知编译器将有一个这种函数
函数原型 (prototype) 必须和函数签名 (signature) 匹配, 虽然参数名字可以变化
函数原型 (prototype) 必须和函数签名 (signature) 匹配, 虽然参数名字可以变化
函数原型通常放在一个单独的头文件中, 将函数原型和函数的实现隔离开来
函数可调用它们自身 递归 (Recursion)
函数可调用它们自身 递归 (Recursion)
函数可调用它们自身 递归 (Recursion)
全局变量 (Global Variables) foo() 函数被调用了多少次? 使用一个全局变量 - 可被任何函数访问 int numcalls = 0; 全局变量 void foo() { ++numcalls; } int main() { foo(); foo(); foo(); cout << numcalls << endl; // 3 return 0; }
作用域 (Scope) 变量在哪里声明, 决定了变量在哪里能被访问 numcalls 具有全局作用域, 能被任何函数访问
作用域 (Scope) 变量在哪里声明, 决定了变量在哪里能被访问 numcalls 具有全局作用域, 能被任何函数访问 result 具有函数作用域, 每个函数有自己单独的 result 变量
传值 (value) 还是传引用 (reference) Pass by value vsby reference 目前调用函数都是传值 - 形参是实参的拷贝. 函数内对形参变量的修改不会影响函数外的变量 ( 包括实参 ). 输出结果
传值 (value) 还是传引用 (reference) Pass by value vsby reference main 函数作用域 q=3 输出结果
传值 (value) 还是传引用 (reference) Pass by value vsby reference main 函数作用域 increment 函数作用域 q=3 a=3 输出结果
传值 (value) 还是传引用 (reference) Pass by value vsby reference main 函数作用域 increment 函数作用域 q=3 a=4 输出结果
传值 (value) 还是传引用 (reference) Pass by value vsby reference 如果想修改原来的变量而不是复制原来的变量, 可以传递引用 (reference) 如用 int&a 代替 inta 输出结果
传值 (value) 还是传引用 (reference) Pass by value vsby reference main 函数作用域 q=3 输出结果
传值 (value) 还是传引用 (reference) Pass by value vsby reference main 函数作用域 increment 函数作用域 q=3 a 输出结果
传值 (value) 还是传引用 (reference) Pass by value vsby reference main 函数作用域 increment 函数作用域 q=4 a 输出结果
实现 swap 函数 : 交换两个变量 main 函数作用域 q=3 r=5
实现 swap 函数 : 交换两个变量 main 函数作用域 q=3 r=5 swap 函数作用域 a b
实现 swap 函数 : 交换两个变量 // 执行完这一句 main 函数作用域 q=3 r=5 swap 函数作用域 t=3 a b
实现 swap 函数 : 交换两个变量 main 函数作用域 // 执行完这一句 q=5 r=5 swap 函数作用域 t=3 a b
实现 swap 函数 : 交换两个变量 main 函数作用域 // 执行完这一句 q=5 r=3 swap 函数作用域 t=3 a b
返回多个值 Returnn 语句只能返回一个值, 引用参数可用于输出结果
默认参数值 Default values in parameters 默认参数一律靠右 #include <iostream> using namespace std; int divide (int a, int b=2){ int r = a/b; return (r); } int main (){ cout << divide (12) << '\n'; cout << divide (20,4) << '\n'; return 0; }
#include <iostream> using namespace std; 内联函数 Inline Functions 指示编译器内联展开, 可避免函数调用开销 ; 对于包含循环的或复杂代码, 编译器仍作为普通函数 inline string concatenate (const string& a, const string& b){ return a+b; } int main (){ string s= Li, w = Wang ; string full = concatenate(s,w); return 0; }
函数的 Declaring 声明与定义 defining 函数使用前须声明 Declaring functions void swap(int &a, int &b); // 使用前先声明 int main(){ int x = 3, y = 4; swap(x,y); std::cout<<x<< <<y<< \n ; return 0; } void swap(int &a, int &b) { int t = a; a = b; b = t; }
库 (Librarys) 库的发布包含 :1) 头文件, 其中有函数原型的说明 ;2) 二进制的.dll 或.so 文件包含了 ( 编译过的 ) 函数实现 - 好处 : 你不需要共享你的.cpp 源代码文件!
库 (Librarys) 库的发布包含 :1) 头文件, 其中有函数原型的说明 ;2) 二进制的.dll 或.so 文件包含了 ( 编译过的 ) 函数实现 - 好处 : 你不需要共享你的.cpp 源代码文件!
库 (Librarys)-cmath 我们根本不需要自己实现之前的 raisetopower 和 squareroot 函数, 因为作为标准库的一部分 cmath 库已经实现了 pow 和 sqrt 函数 我们只需要调用它们!
作业 1. 不运行程序, 说出程序输出结果
2. 指出下列程序中的错误 1)
2)
3)
4)
5)
6)
3. 编写一个函数计算一个已知半径的圆的面积 函数参数采用引用参数和返回值两种方式返回结果 格式如下 : void circlearea( double r, double& A); double circlearea(double r); } intmain(){ double r = 23.5, A; //. std::cout<< the area of the circle is : <<A << \n ; return 0;