intave(int a[], int b) { return0; } // 这种是不可以的,int* a 和 int a[]其实是一样的 // 函数重载使用时不能出现歧义
intave(int& a, int& b) { return0; }
intave(int a, int b) { return0; }
intmain() { int a = 100, b = 100; ave(a, b); // 这种就是不行,出现歧义了 上面两个函数都适用 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
intave(int& a, int& b) { return0; }
floatave(float a, float b) { return0; }
intmain() { char a = 100, b = 100; std::cout << ave(a, b) << std::endl; // 自动转成float std::cout << ave((int)a, (int)b) << std::endl; // 这地方的 转换是临时 的变量,没有固定的内存地址 }
1 2 3 4 5 6 7 8 9 10
intave(int a, int b) { return0; }
intave(constint a, constint b) { return0; } // 不可以重载,是以值传参,不能修改内存里面的值,所以const形同虚设
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
intave(int& a, int& b) { return0; }
intave(const& int a, const& int b) { return0; } // 可以重载, intmain() { int a = 100, b = 100; constint c = 20, d = 10; std::cout << ave(a, b) << std::endl; // 非调用第一个 std::cout << ave(c, d) << std::endl; // 常量执行第二个 }
// 函数重载的时候不能默认参数 编译器分不清
函数模板(C++内容)
函数模板(Function Template)是 C++ 中的一种通用编程技术,允许程序员编写可以操作多种数据类型的函数,而无需为每种数据类型单独重写代码。函数模板通过引入模板参数,使函数的类型可以在调用时动态确定。
1 2 3 4
template <typename type1> type1 ave(type1 a, type1 b) { return (a + b) / 2; }
template<typename type1> type1 bigger(int a, int b) { return a > b ? a : b; } // 例外 //template<> int* bigger(int* a, int* b) { return *a > *b ? a : b; } float* bigger(float* a, float* b) { return *a > *b ? a : b; }
template<typename type1> type1 ave(type1 a, type1 b, type1 c) { return (a + b + c) / 2; }
intmain() { // 本来是想着减少内存开销,传入指针,结果发现,传入的是地址 int a{ 100 }, b{ 200 }, c{ 300 }; c = *bigger(&a, &b); c = *ave(&a, &b, &c); //相当于把内存地址加起来除以3 }
auto decltype
1️⃣auto 不保留const属性 const int a{ 10 };auto b = a; 这里的b就是int类型 。
2️⃣ auto 会优先推断为值类型而非引用类型。
1 2 3
int b{200}; int& l{b}; auto c = l; // 这里l还是int类型
3️⃣ auto 利用函数返回值来确定类型的时候,函数会执行。
1
auto x = ave(1,2); // ave(1,2)会执行 x的类型根据ave函数的返回类型来确定
根据特性2️⃣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#inlcude <iostream>
// auto 拖尾函数 autobigger(int& a, int& b)->float// 转成float类型了 int& bigger(int& a, int& b)// 这里改成auto不行,会把&转成int { return a > b ? a : b; } intmain() { int a{100}; int b{200}; // 能这么写是因为返回值不是临时变量,左值 // bigger(a, b) = 500; // 比较a 和 b 哪个数大,大的 改成500; }
decltype关键字
1 2 3
int a{}; unsigned b{}; decltype(a-b) x; // 相当于unsigned x; 有符号数和无符号运算,结果为无符号数
如果表达式没有经历过运算,那么类型是一样的, 可以保留引用属性 (引用必须初始化)
(没有固定内存地址的情况)如果经历过运算了,会根据结果的类型来推断类型
(有固定内存地址的情况)
1 2 3 4
int a{100}; int* pa{&a};
decltype(*pa) x = a;// x 是int 类型的引用
decltype(pa[5]) x; 相当于int& x pa[5]是有地址的,只是不归我们访问而已
1 2 3 4
autobigger(int& a, int& b)->decltype(a > b ? a : b) { return a > b ? a : b; }
1 2 3 4
decltype(auto) bigger(int& a, int& b) { return a > b ? a : b; }
推断函数模板返回类型
1 2 3 4 5 6 7 8 9 10 11
template<typename T1, typename T2> T1 ave(T2 a, T1 b)// T1 { return (a + b) / 2; }
intmain() { // 返回类型是由后面的决定的 ave(100.02f, 200); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include<iostream>
template<typename T1, typename T2> delctype(auto)bigger(T1& a, T2& b) { return a > b ? a : b; }
intmain() { float a = 50; int b = 50000; // float& lx = b; bigger(a, b); // 结果是个float引用,但是不能指向int类型 std::cout << b; }
函数模板参数的默认值
1 2 3 4 5 6 7 8 9
#include<iostream> // 返回值默认为int类型, 建议写在前面 // 另一种写法, 可以不指定了,跟着T1 走 // template<typename T1, typename T2, typename TR = T1> template<typename TR = int, typename T1, typename T2> TR ave(T1 a, T2 b) { return (a + b) / 2; }
函数模板可以有非类型的模板参数
1 2 3 4 5 6 7
template<typename type1, int max, int min> boolAddHp(type1& hp, type1 damage) { hp -= damage; if (hp > max) hp = max; return hp < min; }
实践,试下这个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include<iostream> template<int max, int min, typename type1> // 建议将 非类型参数写在前面 boolChangeHp(type1& hp, type1 damage)// max 和 min 不是变量 { hp -= damage; if (hp > max) hp = max; return hp < min; }
intmain() { int hp = 2500; // const int x = 2500; // ChangHp<x,1000>(hp, 100); // 这样会报错,x 是常量才可以,这也说明了max和min不是变量 ChangHp<2000,1000>(hp, 100); // <>里面的数据需要指定 std::cout << hp; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// 指定默认值 #include<iostream> // 指定默认值之后,在main里面就不需要<>来指定max min的值了 template<int max = 2000, int min = 1000, typename type1> boolChangeHp(type1& hp, type1 damage) { hp -= damage; if (hp > max) hp = max; return hp < min; }
intmain() { int hp = 2500; ChangHp(hp, 100); std::cout << hp; }
将非类型参数写在后面
1 2 3 4 5 6 7 8
// 将max 和 min 转换为type1类型 template<typename type1, type1 max = 2000, type1 min = 1000, > type1 类型 boolChangeHp(type1& hp, type1 damage) { hp -= damage; if (hp > max) hp = max; return hp < min; }