C++ Primer 函数、编程模块(七)

这篇博客深入探讨了C++中的函数与结构体的交互,包括如何初始化结构体成员,以及使用内联函数、默认参数、函数重载和函数模板。还详细介绍了如何操作string对象和数组,以及使用函数指针和函数指针数组。此外,还讨论了递归函数的工作原理及其注意事项。
摘要由CSDN通过智能技术生成

目录

函数与结构体:

函数与string:

函数与array对象:

递归函数:

函数指针:

函数指针数组:

typedef简单用法:

内联函数(inline):

函数的默认参数:

函数重载:

函数模板

函数与结构体:

#include <iostream>
#include <string.h>
using namespace std;

#define MAX 64									// 数组最大长度

typedef struct INFO
{
	char name[MAX];
	int age;

public:
	INFO()										// 结构体默认构造函数
	{
		//char* temp = "hefei";					// invaild "hefei" -> const char*   temp   -> char*
		//name = "hefei";						// invaild "hefei" -> const char*	name   -> 字符数组
		//string str_name = "hefei";			// vaild   "hefei" -> const char*	string -> C++类(运算符重载)		!!反过来不行
		strcpy_s(name, MAX, "hefei");			// 第二个参数写成 (strlen("hefei") + 1) 也可以,但记住加一,因为 C 的字符串有一个 '\0'结束符
		age = 21;
	}
}_Info;

_Info update()
{
	_Info temp;
	strcpy_s(temp.name, MAX, "coliy");
	temp.age += 1;
	return temp;
}

int main()
{
	INFO info = update();
	cout << "info.name = " << info.name << endl;//coliy
	cout << "info.name = " << info.age << endl;	//22
	return 0;
}


函数与string:

#include <iostream>
using namespace std;

void display(string* arr)
{
	for (int i = 0; i < arr->size(); ++i)
		cout << arr[i] << endl;
}

int main()
{
	string arr[2] = 
	{
		"hefei",
		"coliy"
	};
	display(arr);
	return 0;
}

函数与array对象:

#include <iostream>
#include <array>							// 包含头文件
using namespace std;

void update(array<string, 2>* _arr)
{
	_arr->at(0) = "hefei";					// 相对于 (*_arr)[0]
	_arr->at(1) = "coliy";					// 相对于 (*_arr)[1]
	
}

int main()
{
	array<string, 2> arr1 =
	{
		"name1",
		"name2"
	};

	//array<string, 2> arr2 = arr1;			// 模板类赋值是 -> 深拷贝
	//arr2[1] = "coliy";
	//cout << arr1[1];						// name1

	update(&arr1);
	for (int i = 0; i < arr1.size(); ++i)	
		cout << arr1[i] << endl;			// arr1[0] = hefei	// arr11] = coliy

	return 0;
}

递归函数:

注意:使用递归一定要确定结束条件,否则就是一个死循环

递归结束退出:退到调用它的函数的下一条语句,一次类推

CODE:

#include <iostream>
using namespace std;

void find(int _year)
{
	cout << "find wife" << endl;
	if (_year == 2025)
	{
		cout << _year <<"find it" << endl;
		return;
	}
	find(++_year);
	cout << "not find wife" << endl;
}

int main()
{
	int year = 2022;
	find(year);
	return 0;
}

函数指针:

函数也有地址,存储在代码区; 一个指向函数的指针

CODE:

#include <iostream>
using namespace std;

// 圆的面积
double area(int _radius)
{
	return 3.14 * _radius * _radius;
}

// 圆的周长
double perimeter(int _radius)
{
	return 2 * 3.14 * _radius;
}

// 计算
void count(int _radius, double (*pf)(int))
{
	cout << (*pf)(_radius) << endl;		// vaild
	//cout << pf(_radius) << endl;		// vaild
}

int main()
{
	/*************************************************************************
	*				double (*pf)(int)
	* double:		返回类型 (返回类型必须与指向的函数的返回类型相同)
	* pf:			函数指针
	* int:			参数列表 (参数列表必须与指向函数的参数列表一致)
	* 注意: 声明时必须将括号将 *fun 括起来 (运算符优先级)
	* 如果写成: double* fun(int) -> 意味着 fun() 是一个返回指向double类型的指针
	*************************************************************************/
	count(3, area);		//面积 -> 28.26
	count(3, perimeter);//周长 -> 18.84

	return 0;
}


函数指针数组:

#include <iostream>
using namespace std;

// 圆的面积
double* area(int _radius, double* _size)
{
	*_size = 3.14 * _radius * _radius;
	return _size;
}

// 圆的周长
double* perimeter(int _radius, double* _size)
{
	*_size = 2 * 3.14 * _radius;
	return _size;
}

int main()
{
	/*************************************************************************
	*				double* (*pa[2])(int, double*)
	* double*:		返回类型 (返回类型必须与指向的函数的返回类型相同)
	* pa:			是一个数组
	* int, double*	参数列表 (参数列表必须与指向函数的参数列表一致)
	* 拆分理解		一: 运算符优先级规则, pa 先与 [2] 结合, 所以 pa代表一个数组
	*				二: 数组 pa 再与 * 结合, 代表指针数组, 指向数组的第一个元素
	*************************************************************************/
	double* (*pa[2])(int, double*) =
	{
		area,
		perimeter
	};
	double size = 0;
	cout << *pa[0](3, &size) << endl;	//28.26
	cout << *pa[1](3, &size) << endl;	//18.84
	return 0;
}

typedef简单用法:

#include <iostream>
using namespace std;

typedef double* (*pa)(int, double*);

// 圆的面积
double* area(int _radius, double* _size)
{
	*_size = 3.14 * _radius * _radius;
	return _size;
}

// 圆的周长
double* perimeter(int _radius, double* _size)
{
	*_size = 2 * 3.14 * _radius;
	return _size;
}

void test(int (*a)[2])
{
	cout << *(*(a))		<< endl;	// 10
	cout << *(*(a + 1)) << endl;	// 30
	cout << *((*a + 3)) << endl;	// 40
}

int main()
{
	/*************************************************************************
	*				double* (*pa[2])(int, double*)
	* double*:		返回类型 (返回类型必须与指向的函数的返回类型相同)
	* pa:			是一个数组
	* int, double*	参数列表 (参数列表必须与指向函数的参数列表一致)
	* 拆分理解		一: 运算符优先级规则, pa 先与 [2] 结合, 所以 pa代表一个数组
	*				二: 数组 pa 再与 * 结合, 代表指针数组, 指向数组的第一个元素
	*************************************************************************/

	int a[2][2] = { {10, 20},{30, 40}};
	test(a);

	pa p[2] = { area, perimeter};
	double size = 0;
	cout << *p[0](3, &size) << endl;	//28.26
	cout << *p[1](3, &size) << endl;	//18.84
	return 0;
}


内联函数(inline):

(一)、函数调用是有时间和空间开销的。程序在执行一个函数之前需要做一些准备工作,要将实参、局部变量、返回地址以及若干寄存器都压入栈中,然后才能执行函数体中的代码;函数体中的代码执行完毕后还要清理现场,将之前压入栈中的数据都出栈,才能接着执行函数调用位置以后的代码。

(二)、如果函数体代码比较多,需要较长的执行时间,那么函数调用机制占用的时间可以忽略;如果函数只有一两条语句,那么大部分的时间都会花费在函数调用机制上,这种时间开销就就不容忽视。

解决方案:函数调用处直接嵌入函数体的函数称为内联函数,,即在编译时将函数调用处用函数体替换

使用场景: 短小、频繁调用的函数可以声明为内联函数
不宜场景: 如果函数体内代码比较长,使用内联将导致可执行代码膨胀过大。
                如果函数体内出现循环或者其他复杂的控制结构,那么执行函数体内代码的时间将比函数调用的开销大得多。

#include <iostream>
using namespace std;

#define sum(X) X * X;	//宏代替只是简单的代替

inline int add(int a, int b)	//注意, 在函数定义前添加inline关键字, 在声明添加无效
{
	return a + b;
}

int main(void)
{
	int a = 5, b = 5;
	int c = sum(5 + 5);		// a + b * b + a 
	cout << c << endl;		// 35

	int value = sum(a, b);	// 10
	cout << value << endl;
	return cin.get();
}

函数的默认参数:

(一)、参数的值也可以是表达式

(二)、如果某个参数是表达式,那么它后面的参数必须都是默认参数

(三)、默认参数可以放在函数声明或者定义中,但只能放在两者之一(一般放在函数声明)

(四)、函数重载时谨慎使用默认参数值

#include <iostream>
using namespace std;

/*函数重载的时候谨慎使用, 有多个匹配的选项, 编译器不知道调用哪一个, 所以报错*/
//void test(int a)		
//{
//	cout << "Hello World" << endl;
//}

int fun()
{
	return 1;
}

void test(int a, int b = 500, int c = fun())
{
	cout << "b" << b << endl;
	cout << "c" << c << endl;
}

int main(void)
{
	int a = 5;
	int b = 50;
	test(a);
	return cin.get();
}

函数重载:

  • 函数名称必须相同。
  • 参数列表必须不同(个数不同、类型不同、参数排列顺序不同等必须有一个不同)。
  • 函数的返回类型可以相同也可以不相同。
  • 仅仅返回类型不同不足以成为函数的重载。
  • 作用: 减少了函数名的数量,避免了名字空间的污染
#include<Windows.h>
#include<iostream>
using namespace std;

// 仅返回类型不行,参数列表必须有一个不同
//void Add(int a, int b)
//{
//	return a + b;
//}

int Add(int a, int b)
{
	return a + b;
}

double Add(double a, double b)
{
	return a + b;
}

float Add(float a, float b)
{
	return a + b;
}
int main()
{
	cout << Add(1, 2) << endl;
	cout << Add(3.5, 4.5) << endl;
	cout << Add(2.22, 3.33) << endl;
	return 0;
}

函数模板

函数模板的写法如下:

template <typename 类型参数1, typename 类型参数2, ...> // typename 也可以写成 class
返回值类型  模板名(形参表)
{
    函数体
}

简单用法:

编译器由模板自动生成函数的过程叫模板的实例化。由模板实例化而得到的函数称为模板函数。

模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码。

可以去参考这博客,函数模板,没有写类模板:

https://blog.csdn.net/weixin_45738899/article/details/120687055

using namespace std;

template<typename T1, typename T2>
T2 Swap(T1& x, T2& y)
{
	cout << x << " " << y << endl;
	return x + y;
}
int main()
{
	int n = 1;
	double m = 2.5;
	cout << Swap(n, m) << endl;	//3.5
	return cin.get();
}

总结: 对着我的目录去找别人写的博客, 他们写的更细

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值