1、C++模板编程
1)函数模板
#include <iostream>
using namespace std;
// 声明一个泛型类型T,参数化数据类型
template <typename T>
// 定义一个函数模板
T man(T a, T b) {
return (a>b?a:b);
}
int main()
{
// 使用的时候没有指定参数类型,编译器会自动推导
cout << "Hello World " << max(6, 2);
return 0;
}
2)模板定义
template <typedef T>
// 使用class效果相同,
// 为了不和类的定义发生歧义,尽量使用typedef
template <class T>
// 也可以定义多个类型,但是定义了一定要用,否则报错
template <typedef T1, typedef T2>
3)函数模板调用
显示调用
max<int,int>(1, 2);
隐式调用(自动推导)
max(1, 2);
总结:模板的定义,相当于定义了一个占位符,这个占位符在编译时确定(理解为直接替换,类似宏定义),占位符的类型由参数来确定。
对于一个函数模板的调用(因为是调用的时候能确定参数类型),编译器会在编译时生成对应函数(模板函数)。
4)类模板
#include <iostream>
using namespace std;
// 声明一个泛型类型T,参数化数据类型
template <typename T1, typename T2>
// 定义一个类模板
class TempClass {
public:
T1 key;
T2 val;
public:
TempClass(T1 k, T2 v){key=k;val=v;};
};
int main()
{
// 定义一个模板类对象,指定泛型类型
TempClass<int, int> test(5, 2);
cout << test.key << " " <<test.val << endl;
// 定义一个模板类对象,指定泛型类型
TempClass<string, int> test2("123", 2);
cout << test2.key << " " <<test2.val << endl;
return 0;
}
}
总结:定义了模板之后,在随后定义的类内部如果使用了这个模板类型,那么这就是个类模板,编译器在检测到使用这个类模板实例化对象之后,会根据指定的参数类型得到模板类,该实例就是这个模板类的实例。
由类模板实例化得到的类叫模板类。
5)类内的函数模板
类内的函数模板只有在被调用的时候才会实例化,这点和函数模板特性一致。
#include <iostream>
using namespace std;
// 声明一个泛型类型T,参数化数据类型
template <typename T1, typename T2>
// 定义一个类模板
class TempClass {
public:
T1 key;
T2 val;
public:
TempClass(T1 k, T2 v){key=k;val=v;};
// 定义一个类内函数模板
void PT(T2 a){cout << "PT " << a;};
};
int main()
{
// 定义一个模板类对象,指定泛型类型
TempClass<int, int> test(5, 2);
test.PT(666);
return 0;
}
注意:模板类型在对象定义的时候就确定了,调用类内模板函数的时候类型要一致。
C++函数模板的详细讲解
C++类模板(模板类)详解
在线测试代码
2、C++标准模板库
1、STL 是 C++ 标准库的一部分
2、STL 就是借助模板把常用的数据结构及其算法都实现了一遍,并且做到了数据结构和算法的分离。
1)容器
图片来源@软件技术爱好者,感谢
C++之STL(标准模板库)介绍
3、RAII机制
RAII是Resource Acquisition Is Initialization(wiki上面翻译成 “资源获取就是初始化”)的简称,是C++语言的一种管理资源、避免泄漏的惯用法。
解决一般的问题,有些操作,比如,分配释放内存,加锁解锁等,需要成对出现,否则就会出现问题,内存泄漏,死锁等。
那么要保证操作的成对,需要在规则上实现,而不是靠用户去操作。
使用资源的一般过程,,
1、获取到资源
2、使用资源
3、释放资源
利用局部变量的自动申请和销毁的特性,结合累的构造和析构方法,实现成对操作的简便化处理。
具体操作如下:
#include <iostream>
using namespace std;
class Body {
public:
Body(){cout << "申请资源(分配/加锁)" << endl;}
~Body(){cout << "释放资源(释放/解锁)" << endl;}
void useBody() {
cout << "使用资源" << endl;
}
};
int main()
{
// 复杂易错的资源管理过程就能做成像使用局部变量那样简单
Body body;
body.useBody();
return 0;
}
QT里面的 QMutexLocker 加锁貌似就是这种思想的体现。
详解C++11 RAII机制