#include<iostream>
#include<string>
using namespace std;
template <typename NameType,typename AgeType>
class Person
{
public:
Person(NameType c_name,AgeType c_age):name(c_name),age(c_age){}
void Show();
NameType name;
AgeType age;
};
template <typename NameType, typename AgeType>//类模板成员函数的类外实现
void Person<NameType,AgeType>::Show()//在加作用域的基础上还要加<>
{
cout << this->age << endl;
}
int main()
{
Person<string, int>p1("张三", 24);
p1.Show();
return 0;
system("pause");
}
类模板没有自动类型推导的使用方式,必须显式的指定类型
如果不想显式指定类型,那么就可以在模板参数列表中指定默认参数,但是也要遵循默认参数的规则,自右向左
template <typename NameType=string,typename AgeType=int>
Person< >p1("张三", 24);
#include<iostream>
#include<string>
using namespace std;
class Student {
public:
void show()
{
cout << "成功!" << endl;
}
};
class Student2 {
public:
void show()
{
cout << "失败!" << endl;
}
};
template <typename T>
class Person {
public:
T name;
};
int main()
{
Person<Student2>p1;
p1.name.show();
return 0;
system("pause");
}
//类模板对象的函数调用,当类模板定义的对象做实参
#include<iostream>
#include<string>
using namespace std;
template <class T1,class T2>
class Person {
public:
Person(const T1 c_name, const T2 c_age) :name(c_name), age(c_age) {};
void Show();
T1 name;
T2 age;
};
template <class T1, class T2>
void Person <class T1, class T2>::Show()
{
cout << "成功!" << endl;
}
//1.显式的接收p1的类型Person<string, int>
void fun(Person<string, int> &p)
{
p.Show();
}
//2.隐式的接收p1的类型(参数模板化)
template <class T1, class T2>
void fun(Person<T1, T2>& p)
{
p.Show();
//这里如果想看T1和T2的类型,可进行打印操作
cout << typeid(T1).name << endl;
cout << typeid(T2).name << endl;
}
//3.整个类模板参数化
template <class T>
void fun(T& p)
{
p.Show();
cout << typeid(T).name << endl;//看下T的类型
}
int main()
{
Person<string, int>p1("孙悟空", 25);
fun(p1);//实参传的是类模板定义的对象,形参肯定接收的是Person<string, int>类型的
//个人认为分为显式传递,半隐传递,全隐传递
//常用就最好显式传递吧!
return 0;
system("pause");
}
类模板作为父类,被子类继承
#include<iostream>
#include<string>
using namespace std;
//类模板作为父类,被子类继承
template <class T>
class Person {
public:
Person(){}
Person(T c_name)//当给定了有参构造时,在有继承的问题下,要给出来默认构造函数,原因我也不知道
{
this->name = c_name;
}
void show();
T name;
};
template <class T>
void Person<T>::show()
{
cout << name << endl;
}
class Province :public Person<string>//string其实就已经给定了父类中的T的类型,其实会有很大的不便性
{
public:
Province()
{
cout << "河南省!" << endl;
}
};
int main()
{
Province p2;
p2.name = 5;//23行已经指定了T的类型为string,但是你这有赋了int型,尽管编译不会出问题
//但输出是有问题的,如下图
p2.show();
return 0;
system("pause");
为了增加灵活性,我们一般就会在子类继承下,加一个参数模板,并且将子类也变成类模板,当调用定义子类对象的时候,确定父类的数据类型。
#include<iostream>
#include<string>
using namespace std;
//类模板作为父类,被子类继承
template <class T>
class Person {
public:
Person(){}
Person(T c_name)
{
this->name = c_name;
}
void show();
T name;
};
template <class T>
void Person<T>::show()
{
cout << name << endl;
}
template <class T1>
class Province :public Person<T1>
{public:
Province()
{
cout << "河南省!" << endl;
}
};
int main()
{
Province<string> p2;
p2.name = "张三";
p2.show();
Province<int> p1;
p1.name = 5;
p1.show();
return 0;
system("pause");
}
类模板分文件的编写。
一般来说,我们编写类的时候,都会将类声明定义在.h文件中,而将具体的类成员函数实现在.cpp文件中实现,完成一个类的全部定义。这一招在类的编写上是成立的。
但在类模板中是不成立的,解决办法是:包含.cpp文件,但是这嫌的很菜鸟,其实可以把两者定义在一个文件中,然后用.hpp的后缀加入主程序中。
类模板和友元函数
全局函数想访问类中的私有权限,只能进行将函数设为友元函数,这是很明显的。
全局函数接收来自类模板中的对象,想访问私有权限也需要将该全局函数设为友元函数,一般我们将设置友元函数,并进行类内实现。类外实现太复杂。
#include<iostream>
#include<string>
using namespace std;
template<class T1,class T2>
class Person
{
public:
friend void fun(Person<string, int>& p1)
{
cout << p1.name << p1.age << endl;
}
Person(const T1 c_name,const T2 c_age):name(c_name),age(c_age){}
private:
T1 name;
T2 age;
};
int main()
{
Person<string, int> p1("孙悟空",99);
fun(p1);
return 0;
system("pause");
}