首页 > 其他分享 >二一、函数(四)

二一、函数(四)

时间:2023-12-15 20:56:22浏览次数:27  
标签:return 函数 二一 int ave main 模板

二一、函数(四)

1、推断函数模板返回类型

1)引:将以下函数改写为一个函数模板

int ave(int a,int b)
{
    return (a+b)/2;
}
int ave(float a,fint b)
{
    return (a+b)/2;
}
double ave(int a,float b)
{
    return (a+b)/2;
}
//参数和返回值为2种数据类型的函数模板
template<typename T1,typename T2>  //模板定义时,可以定义多个类型
T1 ave(T2 a, T1 b)
{
	return (a + b) / 2;
}

int main()
{
	std::cout<<ave(100.55f, 200)<<std::endl;
	std::cout << ave<float,int>(100.55f, 200) << std::endl;  //可以强制性得指定模板中得参数类型
}
//参数和返回值为3种数据类型的函数模板
#include <iostream>
template<typename T1, typename T2,typename T3>  //模板定义时,可以定义多个类型
T3 ave(T2 a, T1 b)
{
	return (a + b) / 2;
}

int main()
{
	std::cout << ave<int,float,double>(100, 200.256f) << std::endl;  //可以强制性得指定模板中得参数类型和返回值类型
}

注:可以将函数模板的返回值,设置在第一个位置,当不知道参数类型的时候,只指定函数类型即可
#include <iostream>
template<typename TR, typename T2,typename T3>  //模板定义时,可以定义多个类型
TR ave(T2 a, T3 b)
{
	return (a + b) / 2;
}

int main()
{
	std::cout << ave<double>(100, 200.256f) << std::endl;  //可以强制性得指定模板中得参数类型和返回值类型
}
//如果传入的参数有一个可以确定参数,那么可以直接写明白参数的类型,不使用模板类型
#include <iostream>
template<typename TR, typename T2,typename T3>  //模板定义时,可以定义多个类型
TR ave(T2 a, T3 b,int c)  //第三个参数使用固定类型
{
	return (a + b) / 2;
}

int main()
{
	std::cout << ave<double>(100, 200.256f,100) << std::endl;  
}

2)decltype回返回引用类型

#include <iostream>
template<typename T1, typename T2>  //模板定义时,可以定义多个类型
auto bigger(T1 a, T2 b)   //使用auto推断函数的返回值,或者decltype(auto) bigger(T1 a, T2 b),auto
{
	return a>b?a:b;
}

int main()
{
	char a = 56;
	int b = 50000000;
	std::cout << bigger(a, b);
}

//使用decltype(auto)可以返回引用类型,可以修改函数值
#include <iostream>
template<typename T1, typename T2>  //模板定义时,可以定义多个类型
decltype(auto) bigger(T1 &a, T2 &b)   //使用auto推断函数的返回值,或者decltype(auto) bigger(T1 a, T2 b),auto
{
	return a>b?a:b;
}

int main()
{
	int a = 56;
	int b = 50000000;
	bigger(a, b) = -250;   //可以修改值
	std::cout << b << std::endl;
}

3)decltype不一定传回引用类型

#include <iostream>
template<typename T1, typename T2>  
decltype(auto) bigger(T1& a, T2& b)   
{
	return a > b ? a : b;  //类型不一样,会进行类型转化,类型转化以后,传出的值就不是一个引用类型了
}

int main()
{
	float a = 56;
	int b = 50000000;
	//float& lx = b;   //不是一个引用类型
	bigger(a, b);   //可以修改值
	std::cout << b << std::endl;
}
2、函数模板参数

1)函数模板默认参数(法一)

#include <iostream>
template<typename TR=int,typename T1, typename T2> //定义函数模板返回值的默认类型
TR ave(T1 a, T2 b)
{
	return (a+b)/2;  
}

int main()
{
	std::cout << ave(100, 200) << std::endl;       //使用默认的返回值类型
	std::cout << ave<float>(100, 200) << std::endl;  //使用指定的函数返回值类型
}

2)函数模板默认参数(法二)

//将函数模板返回值默认类型指定为参数类型
#include <iostream>
template<typename T1, typename T2,typename TR = T1>
TR ave(T1 a,T2 b)
{
	return (a + b) / 2;
}

int main()
{
	std::cout << ave(char(1), 200) << std::endl;  //输出d
}

3)非类型的模板参数

//非类型的函数模板参数
#include <iostream>
template<int max, int min,typename T>  //非类型的函数模板参数,此处的max和min不是变量
bool ChangeHp(T& hp,T damage)
{
	hp -= damage;
	if (hp > max)hp = max;
	//max=200;           //报错,因为max不是变量,是函数模板参数,是常量
	return hp < min;
}

int main()
{
	int hp = 2500;
	ChangeHp<2000,1000>(hp, 100);  //需要指定非类型的函数模板参数的值
	std::cout << hp << std::endl; //输出2000,因为最大值为2000
}
//可以在函数模板定义时,就指定函数模板参数
//非类型的函数模板参数
#include <iostream>
template<int max=2000, int min=1000, typename T>  //模板定义时,直接指定非类型的函数模板参数的值
bool ChangeHp(T& hp, T damage)
{
	hp -= damage;
	if (hp > max)hp = max;
	//max=200;           //报错,因为max不是变量,是函数模板参数,是常量
	return hp < min;
}

int main()
{
	int hp = 2500;
	ChangeHp(hp, 100);  
	std::cout << hp << std::endl; 
}

3)非类型模板参数实现处理固定大小的数组

//计算数组中元素的和
//处理不同元素个数的数组
#include <iostream>

template<typename T,short count>
T ave(T(&ary)[count])                 //并没有强制设置count的值
{
	T all{};
	for (int i = 0; i < count; i++)
		all += ary[i];
	return all / count;
}

int main()
{
	int a[5]{ 1,2,3,4,5 };
	std::cout << ave(a) << std::endl;
}
3、函数模板的本质

编译器根据函数模板给定的参数,生成多个不同类型的函数

//C++
#include <iostream>
template <typename T>
T ave(T a, T b)
{
	return a + b;
}

int main()
{
	ave(100, 200);
	ave(short(100), short(200));
}

//函数调用汇编
ave(100, 200);
000B1991 68 C8 00 00 00       push        0C8h   //200
000B1996 6A 64                push        64h    //100
000B1998 E8 48 F8 FF FF       call        ave<int> (0B11E5h)   //函数调用
000B199D 83 C4 08             add         esp,8  
	ave(short(100), short(200));
000B19A0 68 C8 00 00 00       push        0C8h  
000B19A5 6A 64                push        64h  
000B19A7 E8 06 F9 FF FF       call        ave<short> (0B12B2h)  //函数调用
000B19AC 83 C4 08             add         esp,8  
    
//注:可以发现,调用同一个函数,调用的内存地址不一样,说明编译器根据函数模板,自动生成了两个ave()的函数
4、练习:排序工具
//需求:利用函数模板实现以下函数:能够给数组内的元素自动排序
int a[5]{2302,5212,3654,9740,5200};
Sort(a,5);

short a[5]{2302,5212,3654,9740,5200};
Sort(a,5);

std::string a[5]{"abc","bcd","cde","fgh","ijk"}
Sort(a,5)
//不使用函数模板
#include <iostream>

void Swap(int& a,int& b)
{
	int tmp{ a };
	a = b;
	b = tmp;
}

void Sort(int* ary,unsigned count,bool Bigsort = true)
{
	for(int i=1;i<count;i++)
		for (int i = 1; i < count; i++)
		{
			bool bcase = Bigsort ? ary[i] > ary[i - 1]:ary[i] < ary[i - 1];
			if (bcase) Swap(ary[i], ary[i - 1]);
		}
}
int main()
{
	int a[5]{ 2302,5212,3654,9740,5200 };
	Sort(a, 5);
	for (auto x : a)std::cout << x << std::endl;
}
//使用函数模板实现上述功能
#include <iostream>

template<typename T>
void Swap(T& a, T& b)
{
	T tmp{ a };
	a = b;
	b = tmp;
}
template<typename T>
void Sort(T* ary, unsigned count, bool Bigsort = true)
{
	for (T i = 1; i < count; i++)
		for (T i = 1; i < count; i++)
		{
			bool bcase = Bigsort ? ary[i] > ary[i - 1]:ary[i] < ary[i - 1];
			if (bcase) Swap(ary[i], ary[i - 1]);
		}
}
int main()
{
	int a[5]{ 2302,5212,3654,9740,5200 };
	short b[5]{ 2302,5212,3654,9740,5200 };
	Sort(a, 5);
	for (auto x : a)std::cout << x << std::endl;
	std::cout << "+++++++++++++++++++++++++++++" << std::endl;
	Sort(b, 5);
	for (auto x : a)std::cout << x << std::endl;
}

标签:return,函数,二一,int,ave,main,模板
From: https://www.cnblogs.com/piaolaipiaoqu/p/17904165.html

相关文章

  • 无涯教程-Java - int compareTo(String anotherString)函数
    此方法按字典顺序比较两个字符串。intcompareTo-语法intcompareTo(StringanotherString)这是参数的详细信息-anotherString  - 要比较的字符串。intcompareTo-返回值如果两个字符串相等则值为0,如果大于则>0,小于则<0。intcompareTo-示例publicclassTes......
  • 无涯教程-Java - int compareTo(Object o)函数
    此方法将此字符串与另一个对象进行比较。intcompareTo-语法intcompareTo(Objecto)这是参数的详细信息-o  - 要比较的对象。intcompareTo-返回值两个对象比较,如果相等,则返回0,如果大于后面对象,则返回>0,否则返回<0intcompareTo-示例publicclassTest{p......
  • 无涯教程-Java - String Buffer & String Builder函数
    StringBuffer和StringBuilder类在需要对字符串进行大量修改时使用。与字符串不同,可以不停地修改StringBuffer和Stringbuilder类型的对象,而不会留下很多新的未使用对象。StringBuilder类是从Java5开始引入的,StringBuffer和StringBuilder之间的主要区别是StringBuilders......
  • 无涯教程-Java - toUpperCase()函数
    该方法返回指定的char值的大写形式。toUpperCase()-语法chartoUpperCase(charch)这是参数的详细信息-ch  - 原始字符类型。toUpperCase()-返回值此方法返回指定的char值的大写形式。toUpperCase()-示例publicclassTest{publicstaticvoidmain(Str......
  • c语言递归函数
    @TOC前言一、递归的理解:递归函数:函数自己调用自己的,叫做递归调用。例如:voidfun(void){printf("Hellow!");fun();}二、循环角度理解递归:递归的本质就是循环。循环可以完全代替递归,但是递归在某些情况下代码会更简洁一点。可控递归三要素:voidfun(inti)//1.循环控制变......
  • 无涯教程-Java - isWhitespace()函数
    该方法确定指定的char值是否为空格,包括空格,制表符或换行符。isWhitespace()-语法booleanisWhitespace(charch)这是参数的详细信息-ch  - 原始字符类型。isWhitespace()-返回值如果传递的字符确实是空格,则此方法返回true。isWhitespace()- 示例publiccla......
  • 无涯教程-Java - isDigit()函数
    该方法确定指定的char值是否为数字。isDigit()-语法booleanisDigit(charch)这是参数的详细信息-ch  - 原始字符类型。isDigit()-返回值如果传递的字符确实是数字,则此方法返回true。isDigit()-示例publicclassTest{publicstaticvoidmain(String......
  • pandas.array() 与 numpy.array() 函数的区别
    https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.array.html#pandas.array`pandas.array()`和`numpy.array()`都是用于创建数组的函数,但它们在一些方面有所不同¹²:1.**数据类型**:`numpy.array()`可以创建多维数组,而`pandas.array()`主要用于创建Pandas的`Se......
  • 线性探测法的查找函数 整型关键字的散列映射
    一、 实验目的掌握哈希表二、  实验内容实验题目线性探测法的查找函数整型关键字的散列映射  三、   设计文档 1.   2.   四、   源程序  1. PositionFind(HashTableH,ElementTypeKey){    intflag=0;    Positionp......
  • 两个线程共享一个套接字,其中一个线程使用sendmsg函数不断发送消息到该套接字,另一个线
    以下是使用C语言写的一段代码,实现两个线程共享一个套接字,其中一个线程使用sendmsg函数不断发送消息到该套接字,另一个线程使用recvmsg函数不断接收该套接字的消息,并打印出来的功能点击查看代码#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.......