IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【c++】基础之函数 -> 正文阅读

[C++知识库]【c++】基础之函数

一、函数的定义

函数从形式上看分为两类:有参函数和无参函数。

1、无参函数

在调用无参函数时,主调函数不向被调函数传递参数。无参函数通常用来执行指定的一组操作。比如:输出一串*号。
语法:

类型名 函数名(){
	函数体
}

或

类型名 函数名(void){
	函数体
}

函数调用:

函数名();

举个例子:

#include<iostream>

using namespace std;

void my_print() {//自定义函数
	cout << "********" << endl;
}

int main(void) {
	my_print();//函数调用

	return 0;
}

2、有参函数

在调用函数时,主调函数在调用被调函数时,通过参数向被调函数传递数据,一般情况下,执行被调用函数时会得到一个返回值,供主调函数使用。
语法:

类型名 函数名(形参){
	函数体
}
//调用:
函数名(实参)

实例:

#include<iostream>

using namespace std;

int add(int x,int y) {//被调函数,x,y为形参
	return x + y;//获得函数返回值
}

int main(void) {
	int sum;
	sum = add(1,2);//1,2为实参
	cout << sum << endl;

	return 0;
}
//输出结果为 3
函数返回值:
(1)函数返回值是通过函数中return语句获得的。一个函数中可以有一个以上的return语句。
(2)函数值类型必须是一个确定的类型,函数类型决定返回值类型。
(3)对于不带返回值的函数,应当定义函数为“void”类型(空类型),
此时函数体中不得出现return语句。

2.1参数传递

2.1.1、值传递

将值作为形式参数传入数据
比如:

#include<iostream>

using namespace std;

void swap(int x,int y) {
	int temp = x;
	x = y;
	y = temp;
}

int main(void) {
	int x = 10;
	int y = 20;
	swap(x,y);
	cout << x << endl;
	cout << y << endl;
	return 0;
}
//输出结果为:10
//           20

我们发现x,y并没有做交换,原因就是调用swap这个函数时是把值传进去的,而不是x,y这个地址,swap函数里的x,y与main函数里的下x,y根本不是同一个变量

2.1.2、指针传递

想要达到交换效果,我们可以用指针传递,指针传递传的是地址,下面代码中 p 指向 x 的地址,q 指向 y 的地址。而swap所做的任务是把p、q指向的地址里的值改变。

#include<iostream>

using namespace std;

void swap(int* p,int* q) {
	int temp = *p;
	*p = *q;
	*q = temp;
	cout << "swap函数p指向的地址" << p << endl;
	cout << "swap函数q指向的地址" << q << endl;
	cout << endl;
}

int main(void) {
	int x=10;
	int y = 20;
	int* p = &x;
	int* q = &y;
	swap(p,q);
	cout << "mian函数x的值" << x << endl;
	cout << "main函数y的值" << y << endl;
	cout << endl;

	cout << "mian函数x地址" << &x << endl;
	cout << "main函数y地址" << &y << endl;
	cout << endl;

	cout << "mian函数p指向的地址" << p << endl;
	cout << "main函数q指向的地址" << q << endl;

	return 0;
}
//输出结果:
//swap函数p指向的地址00000001000FF934
//swap函数q指向的地址00000001000FF954

//mian函数x的值20
//main函数y的值10

//mian函数x地址00000001000FF934
//main函数y地址00000001000FF954

//mian函数p指向的地址00000001000FF934
//main函数q指向的地址00000001000FF954

此时我们发现调用swap函数时把p、q指向的地址传进去了,也就时x、y的地址

2.1.3、引用传递

引用传递其实跟指针传递具有相同效果,但是,唯一的区别就是应用变量一旦定义,里面指向的地址位置时不能修改的,相当于 *const p。

#include<iostream>

using namespace std;

void swap(int &p,int &q) {
	int temp = p;
	p = q;
	q = temp;
	cout << "swap函数p指向的地址" << &p << endl;
	cout << "swap函数q指向的地址" << &q << endl;
	cout << endl;
}

int main(void) {
	int x=10;
	int y = 20;
	swap(x,y);
	cout << "mian函数x的值" << x << endl;
	cout << "main函数y的值" << y << endl;
	cout << endl;

	cout << "mian函数x地址" << &x << endl;
	cout << "main函数y地址" << &y << endl;

	return 0;
//结果:
//swap函数p指向的地址0000007E894FFC94
//swap函数q指向的地址0000007E894FFCB4

//mian函数x的值20
//main函数y的值10

//mian函数x地址0000007E894FFC94
//main函数y地址0000007E894FFCB4
}

2.1.4、数组作为函数参数

①数组元素可以做函数实参,但不能做函数形参。
因为形参是在函数调用时临时分配存储单元,不可能为数组元素单独分配存储单元(数组是一个整体,在内存中占连续一段存储单元)。当数组元素作为函数实参时,把实参的值传给形参是 “值传递” 方式,数据传递的方向是 从实参传给形参,单向传递。
②数组名做函数参数(包括实参和形参)。

#include<iostream>
using namespace std;
float average(float array[]) {
	int i;
	float aver, sum = array[0];
	for (i = 1; i < 10; i++) {
		sum += array[i];
	}
	aver = sum / 10;
	return aver;
}
int main() {
	float score[10], aver;
	int i;
	cout << "输入十名学生成绩:" << endl;
	for (i = 0; i < 10; i++) {
		cin >> score[i];
	}
	aver = average(score);
	cout << "平均成绩为:" << aver << endl;

	return 0;
}

实参数组与形参数组类型应一致
数组的传递其实只是将实参数组的首元素地址传给形参数组名,数组名代表数组的首元素地址(形参数组首元素array[0]与score[0]具有同一地址,他们占有同一存储单元)。
注意形参的数组声明要符合规范。

二、函数重载

使用相同的函数名来实现不同的功能,一个相同的函数名他的参数数量,返回类型又可以不同,用来实现其他功能。

bool compare(int a,int b){
	return a>b;
}
bool compare(double a,double b){
	return a>b;
}
int main(){
	int a = 10;
	int b = 20;
	double c = 12.2
	double d = 13.2
	cout << compare(a,b) <<endl;//调用的是第一个compare
	cout << compare(c,d) <<endl;//调用的是第二个compare
}

可以看到,函数名相同但参数类型不同。

三、函数模板

对于上面的函数重载,虽然一个函数名实现了不同的功能,但这样大大加大了代码的冗余度。对于这样的问题我们可以用函数模板解决。
语法:

template 关键字用于声明开始进行泛型编程
typename关键字用于声明泛指类型(也可以用class代替)

//T是一个起始未知的模板类型
template<typename T>
bool compare(T a,T b){
	return a>b;
}

函数模板不允许隐式类型转换,调用时类型必须严格匹配

函数模板还可以定义任意多个不同的类型参数:

#include<iostream>
using namespace std;

template <typename T1,typename T2>
T1 add(T1 a,T2 b) {
	
	return a+b;
}

int main(void) {
	int a = 30;
	float b = 20.4;
	//自动类型推导
	cout << add(a, b) << endl;

	//显示指定类型
	cout << add<float>(a, b) << endl;
	return 0;
}
//结果:50
//     50.4

函数模板跟普通函数一样,也可以被重载
c++编译器优先考虑普通函数,如果函数模板可以产生更好的匹配,那么就选择函数模板,
也可以通过空模板实参列表<>限定编译器只匹配函数模板。

#include <iostream>

using namespace std;

template <typename T>
void fun(T a)
{
    cout << "void fun(T1 a)" << endl;
}

template <typename T1, typename T2>
void fun(T1 a, T2 b)
{
    cout << "void fun(T1 a, T2 b)" << endl;
}

void fun(int a, float b)
{
    cout << "void fun(int a, float b)" << endl;
}

void main()
{
    int a = 0;
    float b = 0.0;
    fun(a);
    fun(a, b); //普通函数void fun(int a, float b)已经能完美匹配,于是调用普通函数
    fun(b, a); //这个调用,函数模板有更好的匹配,于是调用函数模板
    fun<>(a, b); //限定只使用函数模板
    system("pause");
}
//输出结果:
//void fun(T1 a)
//void fun(int a, float b)
//void fun(T1 a, T2 b)
//void fun(T1 a, T2 b)

四、函数的嵌套与递归调用

1、嵌套调用

在定义函数时,一个函数内不能再定义另一个函数,即不能嵌套定义,但却可以嵌套调用,即在调用一个函数的过程中调用另一个函数。
在这里插入图片描述
例题:输入四个整数,找出最大值。

#include<iostream>
using namespace std;
int max2(int a ,int b) {
	if (a > b) {
		return a;
	}
	else {
		return b;
	}
}
int max4(int a, int b, int c, int d) {
	
	int m;
	m = max2(a, b);//将max2的返回值放入m中
	m = max2(m, c);
	m = max2(m, d);
	return m;
}
int main(void) {
	
	int a, b, c, d, max;
	cin >> a;
	cin >> b;
	cin >> c;
	cin >> d;
	max = max4(a, b, c, d);
	cout << "最大值为:" << max << endl;

	return 0;
 }

2、递归调用

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用

函数A
调用函数A

需要注意的是:如果不加终止条件就会无终止地自身调用,从而陷入死循环。

例题:已知第一个学生10岁,后一个学生都比前一个学生大两岁,问第五个学生多少岁?

#include<iostream>
using namespace std;
int age(int n) {
	int a;
	if (n == 1) {
		a = 10;
	}
	else {
		a = age(n - 1) + 2;
	}
	return a;
}
int main(void) {
	cout << age(5) << endl;
	

	return 0;
 }

五、外部函数和内部函数

1、外部函数
在定义函数时,在函数首部地最左端加extern关键字(可以省略),则此函数称为外部函数。外部函数可以被其他文件调用,如果定义时如果省略extern,则默认为外部函数。

extern int fun(参数列表)

2、内部函数(静态函数)
在定义函数时,在函数首部加上static关键字,此时这个函数只能被本文件中其他函数调用,提高了程序的可靠性。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章           查看所有文章
加:2022-10-22 20:56:54  更:2022-10-22 21:01:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 6:04:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码