C++ 模板

模板

函数重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//函数重载:整型版本
int getLargestNumber(const vector<int>& vect) {
int largestNumber{ vect.at(0) };
for (auto& val : vect)
{
if (val > largestNumber) largestNumber = val;
}
return largestNumber;
}

//函数重载:浮点数版本
double getLargestNumber(const vector<double>& vect) {
double largestNumber{ vect.at(0) };
for (auto& val : vect)
{
if (val > largestNumber) largestNumber = val;
}
return largestNumber;
}

int main() {
vector<int> vect1{ 1,2,3,4,5,9,8,7,6,0 };
vector<double> vect2{ 1.1,2.2,3.3,4.4,9.9,8.8,7.7,6.6 };
auto result1 = getLargestNumber(vect1);
auto result2 = getLargestNumber(vect2);
cout << result1 << endl; //输出:9
cout << result2 << endl; //输出:9.9
auto c = getchar();
}
  • 同名函数但函数参数不同或参数类型不同
  • C++ 会根据传入的参数调用对应的函数

函数模板

使用模板来编写处理多种数据类型的通用函数,而不是写多个函数重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 函数模板
template <typename T>
T add(T a, T b) {
return a + b;
}

int main() {
int result1 = add(5, 3); // 实例化为 int 类型
double result2 = add(2.5, 3.5); // 实例化为 double 类型

std::cout << "Result 1: " << result1 << std::endl;
std::cout << "Result 2: " << result2 << std::endl;

return 0;
}
  • 编译器在处理 add 调用时,会根据参数类型生成 add 函数的重载实现

  • 只在必要时生成

  • 可以使用 auto 关键字自动推断返回类型

    • ```c++
      template <typename T1, typename T2>
      auto getBiggerNum(T1 param1,T2 param2) {

      // auto 关键字自动推断返回类型
      return param1 > param2 ? param1 : param2;
      

      }

      int main() {

      int a{ 123 };
      double b{ 987.23 };
      auto result = getBiggerNum(a, b);
      cout << result << endl;  //输出:987.23
      auto c = getchar();
      

      }

      1
      2
      3

      ### 类模板

      #include
      #include
      using namespace std;

//模板类:键值对
template
class KeyValPair
{
public:
KeyValPair(string k, T v) :key{ k }, value{ v } { };
string key;//键
T value; //值
};

//模板类:键值字典
template
class Dic
{
public:
Dic()=default;
void PushBack(KeyValPair val) {
vect.push_back(val);
}
auto operator[](string key) {
for (KeyValPair& pair:vect)
{
if (pair.key == key) {
return pair.value;
}
}
}
vector<KeyValPair> vect;
};

//使用模板类
int main() {
Dic dic;
// { “test1” , 123 } 直接用于创建KeyValPair对象
dic.PushBack({ “test1” , 123 });
dic.PushBack({ “test2” , 456 });
dic.PushBack({ “test3” , 789 });
cout << dic[“test2”] << endl; //输出456
auto c = getchar();
}

1
2
3
4
5
6
7
8
9

### 模板别名

```c++
//模板别名
using myType = MyTemplateType<int,string,double,char>;

myType obj;
//...

模板参数

非类型模板参数不代表一个具体的数据类型,而是一个常量表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
//模板类:非类型模板参数:WIDTH,以及模板参数的默认值
template <typename T = int,T WIDTH = 123>
class MyType
{
public:
MyType() = default;
T getWidth() {
return WIDTH; //使用模板参数
}
};

int main() {
MyType obj; //使用了模板参数的默认值
cout << obj.getWidth() << endl; //输出123
MyType<double,456.1> obj2; //没有使用模板参数的默认值
cout << obj2.getWidth() << endl; //输出456.1
auto c = getchar();
}

总结

  • 以模板为基础的泛型也是一种多态的表现形式,但面向对象的多态是运行时多态,而泛型多态是编译期多态
  • 对于模板类,编译器应该要能同时访问到模板的定义和实现,把模板的定义和实现全部放在头文件中
作者

大下坡

发布于

2023-11-12

更新于

2023-11-12

许可协议