1. 类模板
1.1 类模板基本语法
类模板需要自己传入类型参数,不能自动推导,并且模板的参数列表可以有默认参数。
#include <iostream>
#include <string>
using namespace std;
template<typename AGETYPE,typename NAMETYPE = string> /* 尖括号是模板的参数列表 */
class Person
{
public:
Person(AGETYPE age, NAMETYPE name)
{
this->age_ = age;
this->name_ = name;
}
AGETYPE age_;
NAMETYPE name_;
};
void test_1(void)
{
// Person p1(18,"lagransun"); /* 类模板没有自动类型推导的使用方式 */
Person <int>p1(18,"lagransun"); /* 相当于把int给了AGETYPE,NAMETYPE默认参数是string,如果传参的话就变成你传进去的类型 */
cout << p1.age_ << " " << p1.name_ << endl;
}
int main(void)
{
test_1();
return 0;
}
代码运行结果如下
1.2 类模板中成员函数的创建时机
普通的类中的成员函数在开始时就创建,类模板中的成员函数调用是才会创建。所以,按理说下面代码是可行的,虽然不知道Person
中的成员变量p_
是否能调用PrintPerson1()
或者PrintPerson2()
,但是编译器并不会报错,因为func1()
和func2()
是调用的时候才创建的。
但是很可惜,跟我理解的不一样,报错了。
#include <iostream>
#include <string>
using namespace std;
class Person1
{
public:
void PrintPerson1(void)
{
cout << "Person1" << endl;
}
};
class Person2
{
public:
void PrintPerson2(void)
{
cout << "Person2" << endl;
}
};
template<typename TYPE> /* 尖括号是模板的参数列表 */
class Person
{
public:
TYPE p_;
void func1()
{
p_.PrintPerson1();
}
void func2()
{
p_.PrintPerson2();
}
};
template<typename TYPE>
void test_2(TYPE p)
{
if(typeid(p.p_) == typeid(Person1)) p.func1();
else if (typeid(p.p_) == typeid(Person2)) p.func2();
else printf("都不是");
}
void test_1(void)
{
Person <Person1>p; /* 相当于把int给了AGETYPE,NAMETYPE默认参数是string,如果传参的话就变成你传进去的类型 */
test_2(p);
}
int main(void)
{
test_1();
return 0;
}
修改test_2(),注释掉p.func2(),可以编译
template<typename TYPE>
void test_2(TYPE p)
{
if(typeid(p.p_) == typeid(Person1)) p.func1();
// else if (typeid(p.p_) == typeid(Person2)) p.func2(); /* 报错 */
else printf("都不是");
}
看来是编译阶段调用的时候就会创建这个函数了。代码运行结果如下
1.3 类模板与继承
如果要以类模板为父类进行继承,那么子类有两种继承方式:
- 继承的时候传入父类类模板的参数
- 将要继承的子类也写成类模板
#include <iostream>
#include <string>
using namespace std;
template<typename TYPE> /* 尖括号是模板的参数列表 */
class Person
{
public:
TYPE var_l;
};
class PersonTest1 : public Person<int> /* 继承的时候需要传入模板的参数 */
{
public:
void Func()
{
cout << "成功继承:" << var_l << endl;
}
};
template<typename TYPE1, typename TYPE2> /* 或者继承的类也弄成类模板 */
class PersonTest2 : public Person<TYPE1>
{
public:
TYPE1 var_l;
void Func()
{
cout << "成功继承:" << var_l << endl;
}
};
void test_1(void)
{
PersonTest1 pt;
PersonTest2<int,int> pt2;
pt1.Func();
pt2.Func();
}
int main(void)
{
test_1();
return 0;
}
代码运行结果如下
1.4 类模板成员函数的类外实现
类模板成员函数的类外实现,与普通成员函数的区别就是说明作用域的同时要传入类型(尖括号)
#include <iostream>
#include <string>
using namespace std;
template<typename TYPE1, typename TYPE2> /* 尖括号是模板的参数列表 */
class Person
{
public:
Person(TYPE1 age, TYPE2 name)
{
age_ = age;
name_ = name;
}
void PrintMember();
TYPE1 age_;
TYPE2 name_;
};
template<typename TYPE1, typename TYPE2> /* 类模板成员函数的类外实现,与普通成员函数的区别就是说明作用域的同时要传入类型(尖括号) */
void Person<TYPE1, TYPE2> ::PrintMember()
{
cout << "类模板成员函数的类外实现: " << age_ << " " << name_ << endl;
}
void test_1(void)
{
Person<int ,string> p1(18,"lagransun");
p1.PrintMember();
}
int main(void)
{
test_1();
return 0;
}
代码运行结果如下