难点
首先要知道<> 这个尖括号是什么意思?
<T1, T2>对应的入参应该是 <typename T1,typename T2>;
-
用类模板定义对象的写法如下:
类模板名<真实类型参数表> 对象名(构造函数实际参数表);
AutoPtr myclass(new MyClass()); -
如果类模板有无参构造函数,那么也可以使用如下写法:
类模板名 <真实类型参数表> 对象名;
AutoPtr myclass;
所以尖括号就是用来给类模板入参的。
但是重点在于,它其实也可以给函数模板入参!!!
template <typename T>
class stuTemplate {
public:
char *name;
int age;
float score;
};
template <typename T>
struct stuTemplate2 {
public:
char *name;
int age;
float score;
};
template <typename T>
void stuTemplate3(T a) {
cout << "a = " << a << endl;
return;
};
int main() {
// 类模板和结构体模板是一样的,调用方式
// 类和结构体,除了默认public/private不一样,其余都可以理解为一样;
// <int> 代表的是真实入参
stuTemplate<int> stu;
stuTemplate2<int> stu;
// 函数模板也有两种入参方式
// 1.
int a = 3;
stuTemplate3(a);
// 2.
stuTemplate3<int>(9);
return 0;
}
看下汇编:
第二种方式性能更好。
结论:难点和重点在于,对于函数模板,之前都是函数名()这样的调用方式,以后可以使用第二种方式,使用匿名变量的方式去进行函数调用。
基础知识
函数模板
函数模板
- https://www.runoob.com/cplusplus/cpp-templates.html
- http://c.biancheng.net/cpp/biancheng/view/136.html
理解:
实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)
函数模板在编译器会根据调用类型实例化,对不同的参数类型会生成不同的实体函数
template <class 形参名,class 形参名,......>
返回类型 函数名(参数列表) {
函数体
}
类模板
template<class 形参名,class 形参名,…>
class 类名 {
类体;
};
注意:
typename关键字 与 class关键字 没有任何区别;
一般函数模板用typename,类模板用class, 其实是通用的
template <typename T> //template和typename是类型关键字,模板头;T是虚拟的类型,类型占位符
inline T const& Max(T const& a, T const& b)
{
return a < b ? b : a; //比较两个数大小;
}
int main()
{
int i = 10, j = 20;
cout << "Max():" << Max(i, j) << endl;
double d1 = 3.9, d2 = 2.1;
cout << "Max():" << Max(d1, d2) << endl;
string s1 = "hello";
string s2 = "hfllo";
cout << "Max():" << Max(s1, s2) << endl;
scanf_s("wait");
return 0;
}
类模板
http://c.biancheng.net/cpp/biancheng/view/2992.html
定义:
- 函数模板中定义的类型参数可以用在函数声明和函数定义中,类模板中定义的类型参数可以用在类声明和类实现中。类模板的目的同样是将数据的类型参数化。
作用:
- 一旦声明了类模板,就可以将类型参数用于类的成员函数和成员变量了。换句话说,原来使用 int、float、char 等内置类型的地方,都可以用类型参数来代替。
类模板:
template<class 形参名,class 形参名,…>
class 类模板名 {
类体;
};
template <typename T>
class AutoPtr {
public:
explicit AutoPtr (T *ptr = nullptr) {
std::cout << "set new object" << ptr << std::endl;
_ptr = ptr;
}
~AutoPtr () {
std::cout << "delete object" << _ptr << std::endl;
if (_ptr == nullptr) {
delete _ptr;
}
}
T* operator-> () {
return this->_ptr;
}
T& operator* () {
return *(this->_ptr);
}
private:
T* _ptr;
};
用类模板定义对象的写法如下:
类模板名<真实类型参数表> 对象名(构造函数实际参数表);
AutoPtr<MyClass> myclass(new MyClass());
如果类模板有无参构造函数,那么也可以使用如下写法:
类模板名 <真实类型参数表> 对象名;
AutoPtr<MyClass> myclass;