STL
2025/8/4大约 4 分钟
STL
vector
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v1;
v1.push_back(1);
v1.push_back(2);
v1.push_back(3);
for (int i = 0; i < v1.size(); i++)
{
cout << "v1[" << i << "]:" << v1[i] << endl;
}
return 0;
}
模板
函数模板
泛型编程的基础
思考:如果要比较两个数的大小,那么需要写一个函数来传入两个参数,那个大返回那个。
代码如下:
int max(int i1, int i2) {
return i1 > i2 ? i1 : i2;
}
但是这样的只能比较int类型的数值,如果需要比较float类型的数值,就必须在定义一个函数:
float max(float f1, float f2) {
return f1 > f2 ? f1 : f2;
}
如果要比较doule...
类似的,如果有一个业务逻辑是仅有参数类型不同,但是逻辑都相同,那么是否可以创造一个通用的函数来达成目标?
类似于Java的泛型编程?
在cpp中,类似的功能实现,就是模板编程。
实现
/*声明模板编程,声明一个类型T*/
template <typename T>
T max0(T t1, T t2) {
return t1 > t2 ? t1 : t2;
}
// 测试代码
// 隐式调用,自动推断
int a = max0(1, 2);
cout << "1,2=" << a << endl;
// 显示调用
cout << "1,2=" << max0<int>(1, 2) << endl;
double f1 = max0(1.2, 2.3);
cout << "1.2, 2.3=" << a << endl;
函数重载
一个函数模板,一个普通函数,调用那个函数?
/*声明模板编程,声明一个类型T*/
template <typename T>
T max0(T t1, T t2) {
cout << "函数模板" << endl;
return t1 > t2 ? t1 : t2;
}
int max0(int &t1, char &t2) {
cout << "普通" << endl;
return t1 > t2 ? t1 : t2;
}
int main() {
int a = 65;
char b = 'c';
// 调用普通,普通函数 直接匹配
max0(a, b);
当函数模板和普通函数都匹配,会选择普通函数,来调用。
如果显式的调用函数模板,那么就不会调用普通函数
int main() {
int a = 65;
char b = 'c';
max0(a, b);
// 显式的调用函数模板。
max0<int>(a, b);

- 函数模板和普通都匹配时,调用普通函数
- 如果显式调用函数模板,那么会调用函数模板
- 如果函数模板还产生更好的匹配,那么会调用函数模板
- 即如果调用普通函数会进行隐式类型转换,而函数模板类型正好匹配
类模板
#include <iostream>
#include <vector>
using namespace std;
template <typename T> // 类的参数指定泛型
class A {
public:
A(T a) {
this->a = a;
}
// 成员函数返回值显示虚拟类型
T &getA() {
return a;
}
private :
T a;
};
int main() {
// 类模板定义类对象,必须显式指定类型
A<int> a(1);
cout << "A=" << a.getA() << endl;
return 0;
}
- 类模板用于实现类所需数据的类型参数化
- 类模板在标识支持多种数据结构时显得特别重要,这些数据结构的表示和算法不受所包含的元素类型的影响。
继承中类模板的使用
- 如果父类是普通类,子类是模板类,那和普通的类继承没有区别
- 如果父类是模板类,子类是普通类,子类继承需要指定父类的泛型
- 子类父类都是模板类,那么同上,只不过子类需要声明自己的泛型参数。即指定模板类型
- 子类和父类都是模板类的时候,子类的泛型可以传递到父类的参数上。
父类
template <typename T>
class A {
public:
A(T a) {
this->a = a;
}
// 成员函数返回值显示虚拟类型
T &getA() {
return a;
}
private :
T a;
};
子类
class C : public A<int>{
public:
// 构造函数 显式的指定出来是因为父类没有无参构造器
C (int c, int a): A<int>(a) {
this->c = c;
}
private:
int c;
};
类模板的三种表现方式
使用类模板
头文件任然使用.h
后缀
类模板的实现 使用.hpp
后缀
在使用的时候,不在引入.h
文件,而是引入.hpp
文件
类模板中使用友元
和普通函数的友元是不一样 的。
记得在实现类中添加泛型声明。
不仅要在实现类上添加泛型声明,也要在友元函数定义的地方添加泛型声明,否则不允许访问私有属性
不建议使用太多的友元函数
模板类中的静态成员

