模板
1-普通函数作模板
#include <iostream>
using namespace std;
template <class T>void fun(T m_a, T m_b)//实际上是一行
{
cout << m_a << endl
<< m_b
<< endl;
}
int main()
{ //隐式调用
fun("aa", "vvvv");
fun(11, 33);
fun(1.11111, 2.222222);
//显式调用
fun<string>("abab", "cdcd");
fun<double>(0.11, 0.23232);
}
2-类的成员函数作模板
// 类的成员函数作模板
#include <iostream>
using namespace std;
class add
{
int a;
int b;
public:
//类中声明且在类中实现
template <class T>
void print(T a, T b)
{
cout << a << "\t" << b << endl;
}
template <class T> //函数模板的返回值也可以模板化
T Add(T a, T b)
{
return (a + b);
}
template <class int, class T2, class T3 = int> //函数模板可以缺省
T3 multipy(int a, T2 b)
{
return a * b;
}
//仅在类中声明,在类外实现。
template <class Tint, class TT2 = int>
TT2 m_return(Tint a);
};
//类外实现
template <class Tint, class TT2 = int>//类外实现,必须加上template <class Tint, class TT2 = int>
TT2 add::m_return(Tint a)
{
return a;
};
int main()
{
add a1;
a1.print(1, 3);
cout << a1.Add(22, 33) << endl;
cout << a1.multipy(1.3, 5) << endl;
cout << a1.m_return(99.99) << endl;
}
//只需要知道类外实现成员函数的时候要加上template<未知类型>。
// 模板类, 多文件编写代码时,类模板中函数声明和实现不能分离
#include <iostream>
#include <string.h>
using namespace std;
template <class T1, class T2>
class person
{
protected:
T1 name;
T2 age;
public:
//类中声明
person(T1, T2);
T2 print();
};
//类外定义
template<class T1,class T2>
person<T1,T2>::person(T1 name,T2 age):name(name),age(age){};
//模板类不是实际的类,所有用到类名的地方都必须使用 类名<未知类型> 方法使用,除了构造函数那里不用,因为构造函数名只是根类名相同,但不是类名
template<class T1, class T2>
T2 person<T1 ,T2>::print()
//所有用到类名的地方都必须使用 类名<未知类型> 方法使用
{
return (age+age/2);
}
int main()
{
person <string,int> p1("xiaobai",23);//模板类 必须显式定义对象, 所有用到类名的地方都必须使用 类名<未知类型> 方法使用
cout<<p1.print()<<endl;
}
模板类的派生
1-模板类派生出模板子类
#include <iostream>
#include <string.h>
using namespace std;
template <class T1, class T2>
class person
{
protected:
T1 name;
T2 age;
public:
//类中声明
person(T1 name, T2 age);
T2 print();
};
template <class T1, class T2, class T3>//记得加上这个,T1和T2是父类的,T3是子类的
class boy : public person<T1, T2>
{
protected:
T3 score;
public:
boy(T1 name, T2 age, T3 score) : person<T1, T2>(name, age), score(score){}; //别忘了类名要加<未知类型>
T3 print()
{
cout<<this->age<<"\t"<<this->name;
return this->score;
}
};
//类外定义
template <class T1, class T2>
person<T1, T2>::person(T1 name, T2 age) : name(name), age(age){};
//模板类不是实际的类,所有用到类名的地方都必须使用 类名<未知类型> 方法使用,除了构造函数那里不用,因为构造函数名只是根类名相同,但不是类名
template <class T1, class T2>
T2 person<T1, T2>::print()
//所有用到类名的地方都必须使用 类名<未知类型> 方法使用
{
cout<<this->age<<"\t"<<this->name;
return age*3 ;//
}
int main()
{
person<string, int> p1("xiaobai", 23); //模板类 必须显式定义对象, 所有用到类名的地方都必须使用 类名<未知类型> 方法使用
cout << p1.print() << endl;
boy<string, int, string> PP1("xiao_mao", 33, "88.5");
cout<<PP1.print()<<endl;
}
2-模板类派生出普通类
#include<iostream>
using namespace std;
/*欲得到模板类,就必须定义一个类模板,然后从才能从类模板按需求实例化出某个模板类*/
template<class T>
class A
{
T v1;
public:
void print()
{
cout << "v1=" << v1 << endl;
}
};
/*普通类B 从 模板类A<int> 派生*/
class B :public A<int>//模板类A<int>
{
int a;
public:
B(int a_ = 0) :a(a_) { cout << "constructor was called !" << endl; }
void set(int a_)
{
a = a_;
}
void print()
{
cout << "a=" << a << endl;
}
};
int main()
{
B obj(5);
obj.print();
obj.set(7);
obj.print();
}
//模板操作自定义类型:方法一采用重载函数,将<<重载为友元函数,能访问保护成员。也能打印对象
#include <iostream>
#include<string.h>
using namespace std;
class point
{
protected:
int x;
int y;
string name;
//改正方法
friend ostream&operator<<(ostream &m_cout,const point &m_point)
{
m_cout<<m_point.x<<m_point.y<<m_point.name<<endl;
return m_cout;
};
public:
point(int x, int y,string name):x(x),y(y),name(name){};
};
template< class T>
void print (T object)
{
cout<<object<<endl;
}
int main()
{
print(11);
print("eee");
//利用函数模板 打印基本数据类型不报错
//如果打印自定义类型:比如直接打印对象时,需要重载函数
cout<<"******************************************************************"<<endl;
point pp(11,22,"x and y");
//隐式调用
print (pp);
//显式调用
print<point> (pp);
/*
报错信息
模板.cpp:122:9: error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘point’)
122 | cout<<object<<endl;
*/
}
方法二:采用类的特殊化(具体化,这部分将放到后面统一说明)
//模板操作自定义类型:方法一采用重载函数,将<<重载为友元函数,能访问保护成员。也能打印对象
#include <iostream>
#include<string.h>
using namespace std;
template<class T>
void print(T object)
{
cout<<object<<endl;
cout<<" choose_this "<<endl;
}
class point
{
friend void print<point>(point object);
protected:
int x;
int y;
string name;
//改正方法
public:
point(int x, int y,string name):x(x),y(y),name(name){};
};
template<>
void print<point>(point object)
{
cout<<object.x<<" "<<object.y<<" "<<object.name<<endl;
cout<<" choose_that "<<endl;
}
int main()
{ print(255);
cout<<"*****************************"<<endl;
point pp(11,22,"x and y");
//隐式调用
print (pp);
}
程序结果
255
choose_this
*****************************
11 22 x and y
choose_that
模板的嵌套
//模板嵌套
#include<iostream>
#include<string.h>
using namespace std;
template <class T>
void print(T object)
{
cout<<object<<endl;
};
template<class Ty1 ,class Ty2>
class person
{
friend ostream& operator<<(ostream &m_cout,const person&object)
{
m_cout<<object.name<<" \t"<<object.age<<endl;
return m_cout;
}
protected:
Ty1 name;
Ty2 age;
public:
person(Ty1 name,Ty2 age);
};
template<class Ty1, class Ty2>
person<Ty1 ,Ty2>::person(Ty1 name ,Ty2 age) :name(name),age(age){};
int main()
{
person<string,int>p1("aaaa",22);//类模板显示调用对象,
//显式
print<person<string ,int>>(p1);
//隐式
print(p1);
}
程序结果
aaaa 22
aaaa 22
模板嵌套 二
//模板嵌套
#include<iostream>
#include<string.h>
using namespace std;
template<class Ty1 ,class Ty2>
class person
{
friend ostream& operator<<(ostream &m_cout,const person&object)
{
m_cout<<object.data1<<" \t"<<object.data2<<endl;
return m_cout;
}
protected:
Ty1 data1;
Ty2 data2;
public:
person(Ty1 data1,Ty2 data2);
};
template<class Ty1, class Ty2>
person<Ty1 ,Ty2>::person(Ty1 data1 ,Ty2 data2) :data1(data1),data2(data2){};
template<class T1,class T2>
class DataShow{
protected:
T1 one;
T2 two;
public:
DataShow(T1 one ,T2 two):one(one),two(two){};
void print(){
cout<<one<<"\t"<<two<<endl;
}
};
int main()
{
//类模板必须显式定义对象
person<string ,int> p1("xiao_mao",22);//用person 定义姓名 年龄
person<double ,double> p2(88.88,99.99);// 用person 定义两门分数
DataShow<person<string,int>,person<double,double>> student1(p1,p2);
student1.print();
//采用匿名对象的方法,不必给person起名
DataShow<person<string ,int>,person<double,double>> student2(person<string,int>("xiao_bai",23),person<double,double>(55.55,66.66));
student2.print();
//可以使用using 语法简化代码
using ty =person<string ,int>;
using ty2=person<double,double>;
DataShow<ty,ty2> student3(ty("xiao_huang",24),ty2(66.66,55.66));
student3.print();
}
程序结果:
xiao_mao 22
88.88 99.99
xiao_bai 23
55.55 66.66
xiao_huang 24
66.66 55.66
模板分文件编写
模板的特殊化(具体化)
特化和重载的区别
模板与友元函数
https://cloud.tencent.com/developer/article/1177313