C++ 学习(六)函数、 函数的分文件编写、函数默认参数、函数占位参数、函数重载

21 篇文章 11 订阅

1、函数

函数是将段经常使用的代码封装起来,减少重复代码量。

C++函数

语法:

返回值类型  函数名(参数列表)

{

        函数体语句

        return 表达式

}

下面示例包含了函数声明、函数定义、函数调用、函数形参与实参、参数值传递、函数常见样式(无参无返、无参有返、有参无返及有参有返)。

#include<iostream>
using namespace std;

//定义函数(参数为形参):两个整数相加(函数定义在调用前面,否则报错,也可以先定义函数声明,函数写在调用函数后面,参见下面的函数声明max函数)
int add(int a, int b)
{
	int sum = a + b;
	return sum;
}

//定义函数(值传递):交换两个数值(参数值传递,形参发生改变不影响实参)
void swap(int a, int b)
{
	cout << "交换前形参:a = " << a << " , b = " << b << endl;
	int tmp = a;
	a = b;
	b = tmp;
	cout << "交换后形参:a = " << a << " , b = " << b << endl;

}

//函数声明:提前告诉编译器函数的存在,在定义前调用函数不会报错
//函数声明可以写多次(不建议写多次),但是定义只能写一次
int max(int a, int b);
int max(int a, int b);

//函数常见样式
//1、无参无返
void func1() {
	cout << "这是一个无参无返回值函数" << endl;
}

//2、有参无返:参见上面的swap函数

//3、无参有返
string func3()
{
	return "这是一个无参有返回值函数,这是返回的字符串";
}

//4、有参有返回,参见上面的add函数

int main()
{
	//调用函数 - 两数相加(参数为实参)
	cout << "调用函数:两数相加:add(5, 3) = " << add(5, 3) << endl;;

	cout << "--- 参数值传递,形参发生改变不影响实参 ---" << endl;

	//调用函数 - 交换两数(值传递)
	int x = 5;
	int y = 3;
	swap(5, 3);
	cout << "主函数调用交换函数(值传递)实参值, x = " << x << " , y = " << y << endl;

	//调用函数 - 无参无返
	func1();

	//调用函数 - 无参有返
	cout << func3() << endl;

	//调用声明函数
	cout << "调用函数声明函数max = " << max(3, 5) << endl;

	system("pause");

	return 0;
}

//函数定义(函数已在调用前声明)
int max(int a, int b)
{
	return a > b ? a : b;
}

输出结果

调用函数:两数相加:add(5, 3) = 8
--- 参数值传递,形参发生改变不影响实参 ---
交换前形参:a = 5 , b = 3
交换后形参:a = 3 , b = 5
主函数调用交换函数(值传递)实参值, x = 5 , y = 3
这是一个无参无返回值函数
这是一个无参有返回值函数,这是返回的字符串
调用函数声明函数max = 5

Go语言函数

Go语言函数与C++函数区别:

  1.  函数声明与定义一起,且不区别函数定义的位置
  2.  可以包含多个返回值
package main

import "fmt"

func main() {
	fmt.Println("调用函数:两数相加:add(5, 3) = ", add(5, 3))

	fmt.Println("--- 参数值传递,形参发生改变不影响实参 ---")
	x , y:= 5, 3

	swap(x, y)
	fmt.Printf("主函数调用交换函数(值传递)实参值, x = %d, y = %d\n", x, y)

	fmt.Println("--- 实参通过接收函数返回值交换数据 ---")

	x, y = swap1(x, y)
	fmt.Printf("调用函数可以有多个返回值(返回值写法1 - 返回值没有定义名称) - 实现两数交换: x = %d, y = %d\n", x, y)

	x, y = swap1(x, y)
	fmt.Printf("调用函数可以有多个返回值(返回值写法2 - 返回值定义名称) - 实现两数交换: x = %d, y = %d\n", x, y)
}

//定义函数(参数为形参)
func add(a int, b int) int {
	return a + b
}

//定义函数(值传递):交换两个数值(参数值传递,形参发生改变不影响实参)
func swap(a int, b int) {
	fmt.Printf("交换前形参:a = %d, b = %d\n", a, b)
	a, b = b, a
	fmt.Printf("交换后形参:a = %d, b = %d\n", a, b)
}

//函数可以有多个返回值(返回值写法1 - 返回值没有定义名称):交换两个数
func swap1(a int, b int) (int, int) {
	return b, a
}

//函数可以有多个返回值(返回值写法2 - 返回值定义名称):交换两个数
func swap2(a int, b int) (x int, y int) {
	x, y = b, a
	return
}

输出结果

调用函数:两数相加:add(5, 3) =  8
--- 参数值传递,形参发生改变不影响实参 ---
交换前形参:a = 5, b = 3
交换后形参:a = 3, b = 5
主函数调用交换函数(值传递)实参值, x = 5, y = 3
--- 实参通过接收函数返回值交换数据 ---
调用函数可以有多个返回值(返回值写法1 - 返回值没有定义名称) - 实现两数交换: x = 3, y = 5
调用函数可以有多个返回值(返回值写法2 - 返回值定义名称) - 实现两数交换: x = 5, y = 3

2、函数分文件编写

可以把上面的交换函数swap放在一个公共文件中,供其他文件调用。

C++ 分文件编写

(1)创建.h头文件

在解决方案中,右键单击“头文件” -> 选择“添加” -> 选择“新建项”,如下图所示:

选择“头文件” -> 修改文件名称(.h结尾) -> 单击“添加”按钮,如下图所示:

 

(2)在.h头文件声明函数

#include <iostream>
using namespace std;

//两数交换函数声明
void swap(int a, int b);

(3)创建.cpp源文件

在源文件中创建swap.cpp文件,与创建头文件几乎相同,在学习(一)时已经演示过了,此处不再赘述。

(4)在.cpp源文件中定义函数

在swap.cpp文件中,引用头文件swap.h,即与其关联,代码如下所示:

#include "swap.h"

//定义函数(值传递):交换两个数值(参数值传递,形参发生改变不影响实参)
void swap(int a, int b)
{
	cout << "交换前形参:a = " << a << " , b = " << b << endl;
	int tmp = a;
	a = b;
	b = tmp;
	cout << "交换后形参:a = " << a << " , b = " << b << endl;
}

(5)测试主函数调用(另一个.cpp文件)

创建一个新的.cpp文件,引.h入头文件,在main函数中调用头文件中的swap函数,文件结构如下:

 调用函数文件代码如下:

#include<iostream>
#include "swap.h"
using namespace std;

int main()
{
	//调用头文件中声明的函数
	cout << "调用头文件中声明的函数 swap(5, 3) "  << endl;;
	swap(5, 3);

	system("pause");

	return 0;
}

输出结果

调用头文件中声明的函数 swap(5, 3)
交换前形参:a = 5 , b = 3
交换后形参:a = 3 , b = 5

Go语言调用其它包中的函数

(1)创建公共函数

新建一个文件夹 “19-函数-公用函数”, 此处作为演示使用,实际项目中不建议使用中文名命名文件或文件夹。在该文件夹中创建一个.go文件(common.go),定义函数如下:

package common

import "fmt"

//定义函数(值传递):交换两个数值(参数值传递,形参发生改变不影响实参)
func Swap(a int, b int) {
	fmt.Printf("交换前形参:a = %d, b = %d\n", a, b)
	a, b = b, a
	fmt.Printf("交换后形参:a = %d, b = %d\n", a, b)
}

 注:在Go语言中,若想函数被其它包能够访问,函数名首字母需要大写(其含义为其它语言中的public)

(2)调用公共函数

创建主文件.go,调用公共函数(Swap),文件结构如下图所示:

源码如下:

package main

import (
	"fmt"
	common "testProject/CPlus/19-函数-公用函数"
)

func main() {
	fmt.Println("调用公共函数 swap(5, 3)")
	common.Swap(5, 3)
}

输出结果

调用公共函数 swap(5, 3)
交换前形参:a = 5, b = 3
交换后形参:a = 3, b = 5

3、函数默认参数

C++函数默认参数

函数参数可以设置默认值,调用时若传递了数据,则使用传递的数据,否则使用默认值。

注:

  1. 函数参数中,如果某个位置有默认值,那么这个位置之后的参数都要有默认值
  2. 声明与实现只能有一个能包含参数默认值;如果函数声明有参数默认值,函数实现时就不能有参数默认值,反之亦然。
#include<iostream>
using namespace std;

//声明与实现只能有一个能包含参数默认值,举个例子声明无默认值,实现有默认值
int add(int a, int b, int c);
//int add(int a, int b = 10, int c = 3); //报错:重定义默认参数

//参数默认值:调用时若传数据,则使用传递的数据,否则使用默认值
//如果某个位置有默认值,那么这个位置之后的参数都要有默认值
int add(int a, int b = 10, int c = 3)
{
	int sum = a + b + c;
	return sum;
}

int main()
{
	//函数 - 默认参数
	cout << "调用时传递了所有参数,结果为:" << add(5, 10, 3) << endl;
	cout << "调用时传递了2个参数,结果为:" << add(5, 10) << endl;
	cout << "调用时传递了1个参数,结果为:" << add(5) << endl;

	system("pause");

	return 0;
}

//函数定义(函数已在调用前声明)
int max(int a, int b)
{
	return a > b ? a : b;
}

输出结果

调用时传递了所有参数,结果为:18
调用时传递了2个参数,结果为:18
调用时传递了1个参数,结果为:18

Go语言函数中没有默认参数 

4、函数占位参数

C++函数占位参数

C++中函数的形参列表可以有占位参数,用作占位,调用函数时必须填补该位置。占位参数可以有默认值。

语法:返回值类型 函数名(数据类型) { 函数体 }

#include<iostream>
using namespace std;

//函数 - 占位参数:占位参数可以有默认值
void f1(int a, int = 9)
{
	cout << "函数参数 a = " << a << endl;
}

int main()
{
	//函数 - 占位参数
	//调用函数占位参数
	f1(5, 3);

	system("pause");

	return 0;
}

//函数定义(函数已在调用前声明)
int max(int a, int b)
{
	return a > b ? a : b;
}

输出结果

 函数参数 a = 5

Go语言函数中没有占位参数

5、函数重载

C++函数重载

函数名相同,提高复用性。

函数重载条件:

  1. 同一个作用域下
  2. 函数名相同
  3. 函数参数类型不同,或参数个数不同,或参数顺序不同

 函数返回值不作为函数重载条件,即返回值要相同。

注意:

  1. 引用作为重载条件的使用
  2. 函数重载遇到默认参数,会出现二义性,因此避免重载时有默认参数的情况
#include<iostream>
using namespace std;

//函数 - 函数重载 : 同作用域下同名函数,函数参数类型不同,或参数个数不同,或参数顺序不同
void f1()
{
	cout << "函数 f1 无参" << endl;
}

//参数个数不同
void f1(int a)
{
	cout << "函数 f1(int a) 有一个整型参数" << endl;
	cout << "a = " << a << endl;
}

//参数类型不同
void f1(string a)
{
	cout << "函数 f1(string a) 有一个字符串类型参数" << endl;
	cout << "a = " << a << endl;
}

//参数顺序不同
void f1(int a, string b)
{
	cout << "函数 f1(int a, string b) 有2个参数,第1个整型,第2个字符串类型" << endl;
	cout << "a = " << a << ", b = " << b << endl;
}

void f1(string a, int b)
{
	cout << "函数 f1(string a, int b) 有2个参数,第1个字符串类型,第2个整型" << endl;
	cout << "a = " << a << ", b = " << b << endl;
}

//引用作为重载条件
void f2(int& a)
{
	cout << "函数 f2(int& a) 有一个引用整型参数" << endl;
	cout << "a = " << a << endl;
}

void f2(const int& a)
{
	cout << "函数 f2(const int& a) 有一个常量引用参数" << endl;
	cout << "a = " << a << endl;
}

//函数重载遇到默认参数
void f3(int a)
{
	cout << "函数 f3(int a) 有一个整型参数" << endl;
	cout << "a = " << a << endl;
}

void f3(int a, int b = 3)
{
	cout << "函数 f3(int a, int b = 3) 有2个整型参数,第2个参数有默认值" << endl;
	cout << "a = " << a << ", b = " << b << endl;
}

int main()
{
	//函数 - 函数重载
	//调用重载函数
	f1();
	f1(5);
	f1("Hello");
	f1(5, "Hello");
	f1("Hello", 5);

	cout << endl << " --- 引用作为重载条件 --- " << endl << endl;

	//调用重载函数 - 引用参数
	int a = 7;
	f2(a);
	f2(7);

	cout << endl << " --- 函数重载遇到默认值 --- " << endl << endl;

	//函数重载遇到默认值
	//f3(5); //此处出现二义性,报错,尽量避免函数重载中有默认值的情况
	f3(5, 7);
	
	system("pause");

	return 0;
}

//函数定义(函数已在调用前声明)
int max(int a, int b)
{
	return a > b ? a : b;
}

输出结果

函数 f1 无参
函数 f1(int a) 有一个整型参数
a = 5
函数 f1(string a) 有一个字符串类型参数
a = Hello
函数 f1(int a, string b) 有2个参数,第1个整型,第2个字符串类型
a = 5, b = Hello
函数 f1(string a, int b) 有2个参数,第1个字符串类型,第2个整型
a = Hello, b = 5

 --- 引用作为重载条件 ---

函数 f2(int& a) 有一个引用整型参数
a = 7
函数 f2(const int& a) 有一个常量引用参数
a = 7

 --- 函数重载遇到默认值 ---

函数 f3(int a, int b = 3) 有2个整型参数,第2个参数有默认值
a = 5, b = 7

Go语言函数中没有函数重载

Go 语言的设计理念就是 “显式大于隐喻”,追求明确,显式。

函数重载和参数默认值有隐喻的含义。调用者只看函数名,可能没法知道这个默认值,又或是入参不同等,C++函数重载有默认值时,会出现二义性(见上例),Go语言避免这样的情况发现,因此Go语言中没有函数重载与默认值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值