1.2 函数的定义
1.2 函数的定义
前 面 我 们 用 过 了 很 多 C++ 标 准 函 数 , 但 是 这 些 标 准 函 数 并 不 能 满 足 所
有 需 求 。当 我 们 需 要 特 定 的 功 能 函 数 时 ,这 就 需 要 我 们 要 学 会 自 定 义 函 数 ,
根 据 需 求 定 制 想 要 的 功 能 。
1 . 2 . 1 函 数 定 义 的 语 法
函 数 体
返 回 类 型 函 数 名 ( 参 数 列 表 )
{
}
关 于 函 数 定 义 的 几 点 说 明 :
(1 ) 自 定 义 函 数 符 合 “ 根 据 已 知 计 算 未 知 ” 这 一 机 制 , 参 数 列 表 相 当
于 已 知 , 是 自 变 量 , 函 数 名 相 当 于 未 知 , 是 因 变 量 。 如 程 序 eg1.1_2 中 的
abs 函 数 的 功 能 是 根 据 给 定 的 数 x 计 算 x 的 绝 对 值 , 参 数 列 表 中 x 相 当 于 已
知— 自 变 量 ,abs 函 数 的 值 相 当 于 未 知— 因 变 量 。
( 2 ) 函 数 名 是 标 识 符 , 一 个 程 序 中 除 了 主 函 数 名 必 须 为 main 外 , 其
余 函 数 的 名 字 按 照 标 识 符 的 取 名 规 则 命 名 。
(3 ) 参 数 列 表 可 以 是 空 的 , 即 无 参 函 数 , 也 可 以 有 多 个 参 数 , 参 数 之
间 用 逗 号 隔 开 , 不 管 有 没 有 参 数 , 函 数 名 后 的 括 号 不 能 省 略 。 参 数 列 表 中
的 每 个 参 数 , 由 参 数 类 型 说 明 和 参 数 名 组 成 。 如 程 序 eg1.1_2 中 abs 函 数
的 参 数 列 表 只 有 一 个 参 数 , 参 数 数 据 类 型 是 double, 参 数 名 是 x 。
( 4 ) 函 数 体 是 实 现 函 数 功 能 的 语 句 , 除 了 返 回 类 型 是 void 的 函 数 ,
其 他 函 数 的 函 数 体 中 至 少 有 一 条 语 句 是 “return 表 达 式 ; ” 用 来 返 回 函 数
的 值 。 执 行 函 数 过 程 中 碰 到 return 语 句 , 将 在 执 行 完 return 语 句 后 直 接 退
出 函 数 , 不 去 执 行 后 面 的 语 句 。
( 5 ) 返 回 值 的 类 型 一 般 是 前 面 介 绍 过 的 int、 double、 char 等 类 型 ,
也 可 以 是 数 组 。 有 时 函 数 不 需 要 返 回 任 何 值 , 例 如 函 数 可 以 只 描 述 一 些 过
程 用 printf 向 屏 幕 输 出 一 些 内 容 , 这 时 只 需 定 义 函 数 返 回 类 型 为 void, 并
且 无 须 使 用 return 返 回 函 数 的 值 。
1 . 2 . 2 函 数 定 义 应 用 实 例
根 据 上 述 定 义 , 我 们 知 道 C++ 函 数 形 态 有 以 下 四 类 :
3
(1 ) 返 回 类 型 函 数 名 ( 参 数 列 表 ) 。
(2 ) 返 回 类 型 函 数 名 (
(3 )void 函 数 名 ( 参 数 列 表 )。
(4 )void 函 数 名 (
下 面 我 们 一 起 来 看 几 个 例 子 :
)。
)。
【 例 1 . 2 】给 定 两 个 非 负 整 数 n 和 m , 编 写 函 数 计 算 组 合 数 Cm
分 析 : 首 先 分 析 函 数 的 功 能 , 根 据 给 定 的 n,m 计 算 Cm
n 。
n 。n,m 已 知 , 相
当 于 自 变 量 ; Cm
n 未 知 , 相 当 于 因 变 量 。 设 计 以 下 函 数 :
long long C(int n,int m)
其 中 , 函 数 的 返 回 值 为 Cm
n
, 返 回 类 型 为 long long, 函 数 名 为 C , 参 数
列 表 中 有 两 个 参 数 n,m, 类 型 都 是 int。 函 数 体 是 实 现 函 数 功 能 的 语 句 , 根
m! ∗ (n − m)! 发 现 需 要 三 次 用 到 “ 计 算 一 个 数 的 阶 乘 ” 这 个 功 能 ,
据 Cm
n =
n!
因 此 把 这 个 功 能 独 立 出 来 设 计 一 个 函 数 来 实 现 :
long long f(int n)
该 函 数 的 返 回 值 为 n!, 返 回 类 型 为 long long, 函 数 名 为 f, 需 要 一 个 参
数 n , 类 型 为 int。
综 上 , 该 函 数 的 代 码 如 下 :
1 //eg1.2
2 long long f(int n)
3 {
4 long long ans=1;
5 for(int i=1;i<=n;i++)
6 ans*=i;
7 return ans;
8 }
9
10 long long C(int n,int m)
11 {
12 return f(n)/(f(m)*f(n-m));
13 }
提 示 :
(1 ) 函 数 体 中 的 语 句 可 以 是 对 另 一 个 函 数 的 调 用 。
(2 ) 对 于 较 大 的 n,m 来 说 , 上 述 程 序 可 能 会 产 生 溢 出 。
4
第1章 模块化编程—函数
【 例 1 . 3 】 编 写 函 数 输 出 斐 波 那 契 数 列 的 第 n 项 。 其 中 斐 波 那 契 数 列
f(n) 的 定 义 如 下 :
1.3 函数调用与参数传递
f(1)=0,f(2)=1
f(n)=f(n- 1)+f(n- 2)(n>=2)
分 析 : 因 为 该 函 数 不 需 要 返 回 值 , 只 需 要 输 出 f(n) 即 可 , 所 以 该 函 数
的 返 回 类 型 为 void, 函 数 体 部 分 只 需 计 算 出 f(n) 再 输 出 即 可 。
函 数 代 码 如 下 :
1 //eg1.3
2 void output(int n)
3 {
4 if(n<=2)
5 cout<
两 大 类 : 其 中 一 类 有 返 回 值 , 如 程 序 eg1.1_2 中 的 abs 函 数 、 例 1.2 中 的 f
函 数 和 C 函 数 ; 另 一 类 没 有 返 回 值 , 如 例 1.3 中 的 output 函 数 。
对 于 有 返 回 值 的 函 数 , 调 用 时 必 须 以 值 的 形 式 出 现 在 表 达 式 中 。 比 如
程 序 eg1.1_2 第 16 行 :
mht=abs(x1- x2)+abs(y1- y2);
该 语 句 对 abs 函 数 的 调 用 出 现 在 赋 值 语 句 的 右 边 , 程 序 eg1.2 第 12 行 :
return f(n)/(f(m)*f(n- m));
该 语 句 对 f 函 数 的 调 用 出 现 在 return 语 句 中 , 作 为 C 函 数 的 返 回 值 。
对 于 没 有 返 回 值 的 函 数 ,直 接 写“ 函 数 名 ( 参 数 ) ;”即 可 。如 例 1.3 中 ,
如 果 需 要 输 出 斐 波 那 契 数 列 的 第 10 项 , 用 “output(10); ” 即 可 实 现 。
程 序 可 以 调 用 任 何 前 面 已 经 定 义 的 函 数 , 如 果 我 们 需 要 调 用 在 后 面 定
义 的 函 数 , 就 要 先 声 明 该 被 调 用 的 函 数 。 声 明 方 法 如 下 :
// 声明 sgn 函数
返 回 类 型 函 数 名 ( 参 数 列 表 ) ;
程 序 如 下 :
1 #include
2 using namespace std ;
3 int sgn(int n);
4 int main()
5 {
6 int n;
7 cin>>n;
8 cout<0)?1:-1;
15 }
2 . 形 式 参 数 与 实 际 参 数
函 数 调 用 需 要 理 解 形 式 参 数 与 实 际 参 数 :
(1 )函 数 定 义 中 的 参 数 名 称 为 形 式 参 数 ,如 long long C(int n,int m)
中 的 n 和 m 是 形 式 参 数 , 我 们 完 全 可 以 把 n 换 成 a, 把 m 换 成 b , 再 把 函 数 体
中 的 n 换 成 a,m 换 成 b, 函 数 的 功 能 完 全 一 样 。
(2 ) 实 际 参 数 是 指 实 际 调 用 函 数 时 传 递 给 函 数 的 参 数 的 值 。 如 调 用 函
6
第1章 模块化编程—函数
1.3 函数调用与参数传递
数 C(6,3), 这 里 的 6,3 就 是 实 际 参 数 , 其 中 6 传 递 给 形 式 参 数 n ,3 传 递 给
形 式 参 数 m 。
3 . 调 用 函 数 的 执 行 过 程
调 用 函 数 的 执 行 过 程 如 下 :
( 1 ) 计 算 实 际 参 数 的 值 。 如 程 序 eg1.1_2 中 输 入 x1=1.2, y1=1.5,
x2=2.5, y2=3.8, 程 序 第 16 行 调 用 函 数 abs(x1- x2) 和 abs(y1- y2), 首 先
计 算 参 数 x1- x2=- 1.3, y1- y2=- 2.3,这 里 的 -1.3 和 -2.3 就 是 实 际 参 数 。
(2 ) 把 实 际 参 数 传 递 给 被 调 用 函 数 的 形 式 参 数 , 程 序 执 行 跳 到 被 调 用
的 函 数 中 。如 程 序 eg1.1_2 中 ,调 用 abs(x1- x2) 时 就 会 把 -1.3 赋 值 给 函 数
定 义 中 的 形 式 参 数 x , 然 后 执 行 abs(- 1.3)。
( 3 ) 执 行 函 数 体 , 执 行 完 后 如 果 有 返 回 值 , 则 把 返 回 值 返 回 给 调
用 该 函 数 的 地 方 继 续 执 行 。 如 上 面 的 例 子 中 , 就 会 在 执 行 完 abs(- 1.3)
后 返 回 1.3, 再 执 行 abs(- 2.3) 后 返 回 2.3, 接 着 就 可 以 计 算 出 abs(x1-
x2)+abs(y1- y2) 的 值 等 于 1.3+2.3=3.6, 再 赋 值 给 左 边 的 变 量 mht。
1 . 3 . 2 参 数 传 递
1 . 传 值 参 数
函 数 通 过 参 数 来 传 递 输 入 数 据 , 参 数 通 过 传 值 机 制 来 实 现 。
前 面 的 程 序 中 的 函 数 都 采 用 了 传 值 参 数 , 采 用 的 传 递 方 式 是 值 传 递 ,
函 数 在 被 调 用 时 , 用 克 隆 实 参 的 办 法 得 到 实 参 的 副 本 传 递 给 形 参 , 改 变 函
数 形 参 的 值 并 不 会 影 响 外 部 实 参 的 值 。
【 例 1 . 4 】编 写 程 序 利 用 函 数 交 换 两 个 变 量 的 值 。
1 //eg1.4_1( 错误 )
2 #include
3 using namespace std;
4 void swap(int a,int b)
5 {
6 int t=a;
7 a=b;
8 b=t;
9 }
10
11 int main()
运 行 结 果 :
输 入 :3 4
输 出 :3 4
7