1.第一个最简单的类模板案例
#include
"mainwindow.h"
#include
<QApplication>
#include
<QPushButton>
#include
<QLabel>
template<class
T>
class
run
{
public:
T
w;
void
show()
{
w.show();
}
void
settext()
{
w.setText("A");
}
};
int
main(int
argc,
char
*argv[])
{
QApplication
a(argc,
argv);
run<QPushButton>
run1;
run1.show();
run1.settext();
return
a.exec();
}
2.类模板案例2
#include <iostream>
#include <typeinfo>
using namespace std;
int add(int a,int b)
{
std::cout << "add int\n";
return a + b;
}
double add(double a,double b)
{
std::cout << "add double\n";
return a + b;
}
template<class T>
T add(T a,T b)
{
std::cout << "add T\n";
return a + b;
}
class com1
{
public:
int a;
int b;
int add()
{
return a + b;
}
};
class com2
{
public:
double a;
double b;
double add()
{
return a + b;
}
};
template <class T>
class com
{
public:
T a;
T b;
T add()
{
std::cout << typeid(T).name() << std::endl;
return a + b;
}
};
int main()
{
com<double> comx;
comx.a = 19;
comx.b = 29.8;
std::cout << comx.add() << std::endl; //结果四48.8
com2 com21;
com21.a = 10;
com21.b = 20.9;
std::cout << com21.add() << std::endl; //结果是30.9
return 0;
}
-
多种类型的类模板
案例:
#include<iostream>
#include<string>
//定义两种数据类型的类模板
//STL数据结构,算法,适合任何类型
//定义两种数据类型的类模板
template<class
T1,class
T2>
class
myclass
{
public:
T1
t11;
T2
t22;
myclass(T1
t111,
T2
t222) :t11(t111),
t22(t222)
{
}
void
print()
{
std::cout
<< t11 <<
"
" <<
t22 <<
std::endl;
}
};
void
main()
{
myclass<int,
double>
my1(10, 20.8);
my1.print();
myclass<double,
std::string>
my2(20.8,
"123456abc");
my2.print();
std::cin.get();
}
3.自定义类模板,类模板的默认类型
myArray.h
#pragma
once
//只包含一次,只是针对VS下的
//类模板可以有一个默认的值
template<class
T =
int>
class
myArray
{
public:
myArray();
~myArray();
};
myArray.cpp
#include
"myArray.h"
template <class
T =
int>//每一个函数都需要加上一个默认的值
myArray<T>::myArray()
//类模板成员函数在外部,需要加载类型初始化
{
std::cout
<< "构造"
<< typeid(T).name()
<< std::endl;
}
template <class
T =
int>
myArray<T>::~myArray()
{
std::cout
<< "销毁"
<< typeid(T).name()
<< std::endl;
}
main.cpp
#include
<iostream>
#include
<array>
#include
<string>
#include
"myArray.h"
#include
"myArray.cpp"
//类模板的成员函数没有实例化,不会自动找到,需要手动包含
using
namespace
std;
void
main1()
{
myArray<double>
my1;
myArray<>
my2;//C++11的新功能(如果有默认类型了,这时候类型可以为空)
std::cin.get();
//结果输出
//构造double
//构造int
}
void
main()
{
array<string,
5>strarray = {
"calc",
"mspaint",
"notepad",
"tasklist",
"pause" };
for (int
i = 0;
i <
strarray.size();i++)
{
std::cout
<< strarray[i].c_str()
<< std::endl;
}
std::cin.get();
//运行结果是:
//calc
//mspaint
//notepad
//tasklist
//pause
}
4.数组的模板实现(类似c++中array的功能)
Array.h
#pragma
once
template<class
T,int
n>
class
Array
{
public:
Array();
Array(int
length);
~Array();
int
size();
T
get(int
num);
T & operator [](int
num);//重载[]
void
set(T
data,
int
num);
public:
T *pt;
};
Array.cpp
#include
"Array.h"
template<class
T,
int
n>//int
n不可以修改,不是类的内部成员
Array<T,n>::Array()
{
this->pt
= new
T[n];
}
/*****************************
*初始化length个长度的数组
*****************************/
template<class
T,
int
n>
//每一个函数都必须模板
Array<T,
n>::Array(int
length)
{
this->pt
= new
T[length];
}
/*****************************
*析构数组
*****************************/
template<class
T,
int
n>//每一个函数都必须模板
Array<T,
n>::~Array()
{
//n = 0;
delete[]
this->pt;
}
/*****************************
*获得Array的大小
*****************************/
template<class
T,int
n>
int
Array<T,
n>::size()
{
return
n;
}
/*****************************
*获得第n个元素
*****************************/
template<class
T,
int
n>//每一个函数都必须模板
T
Array<T,
n>::get(int
num)//num是数组的下标
{
if (num
>= n ||
num < 0)//报错
{
//异常
}
else
{
return *(this->pt
+ num);
}
}
/*****************************
*设置第i个元素的值
*****************************/
template<class
T,int
n>
//每一个函数都必须模板
void
Array<T,
n>::set(T
data,int
num)
{
if (num
< 0 || num >=
n)
{
}
else
{
*(pt +
num) =
data;
}
}
/*****************************
*重载[]
*****************************/
template<class
T,
int
n>//每一个函数都必须模板
T&
Array<T,
n>::operator [](int
num)
{
if (num
< 0 || num >=
n)
{
}
else
{
return *(pt
+ num);
}
}
测试Array的主函数:
#include
<iostream>
#include
<string>
#include
"Array.h"
#include
"Array.cpp"
using
namespace
std;
void
main1()
{
Array<int,
5> myarray;
for (int
i = 0;
i <
myarray.size();
i++)
{
//设置第i个元素的值为i
myarray.set(i,i);
std::cout
<< myarray[i]
<< std::endl;
}
std::cin.get();
//打印结果是:
//0
//1
//2
//3
//4
}
/************************************
*通过函数模板实现打印Array中的元素
************************************/
template<class
T,int
n>
//类模板作为参数,类型无比明确
void
print(Array<T,
n> &myArray)
{
for (int
i = 0;
i <
myArray.size();i++)
{
std::cout
<< myArray[i]
<< std::endl;
}
}
void
main()
{
Array<int,
5> myarray;
//调用size()函数,求Array中的大小
for (int
i = 0;
i <
myarray.size();i++)
{
myarray.set(i,i);
}
//通过函数模板实现打印array中的数据
print(myarray);
std::cin.get();
//打印结果是:
//0
//1
//2
//3
//4
}
5.友元类类模板
#include<iostream>
//友元类必须声明类的存在,
//需要声明友元类,必须要与类型相关
template<class
T>
class
myclass;
template<class
T>
class
runclass;
template<class
T>
class
myclass
{
public:
myclass(T
t) :x(t){}
friend
class
runclass<T>;//声明友元类
private:
T
x;//模板友元类
};
template<class
T>
class
runclass
{
public:
void
print(const
myclass<T>
& my)
{
//直接访问传递进来的类的私有变量
std::cout
<< my.x
<< std::endl;
}
};
void
main()
{
myclass<double>
my1(19.8);
//myclass中定义的友元类
runclass<double>
run1;
run1.print(my1);
std::cin.get();
}
6.友元函数
#include<iostream>
template <class
T>
class
myclass;
//这里一定要声明这个友元类
template <class
T>
void
printA(myclass<T>
my);
template <class
T>
class
myclass
{
public:
myclass(T
t) :x(t)
{
}
friend
void
print(myclass<T>
my)
{
std::cout
<< my.x
<< std::endl;
}
//友元函数如果在外部,第一声明要加类型T
//必须要声明类还有函数
friend
void
printA<T>(myclass<T>
my);
private:
T
x;
//模板友元类
//int y;访问与T无关的类型,普通友元类
};
template <class
T>
void
printA(myclass<T>
my)
{
std::cout
<< my.x
<< std::endl;
}
void
main()
{
myclass<int>
my1(10);
myclass<double>
my2(10.9);
printA(my1);
print(my2);
std::cin.get();
//运行结果:
//10
//10.9
}
7.类模板与静态变量,同种类型的实例共享同一个静态变量,不同类的不共享同一个变量
案例:
#include
<iostream>
#include<string>
//类模板的static成员,对象,类名《类型》
//不同类型的静态成员变量,地址不一样
//相同类型的静态成员变量,地址一样
template<class
T>
class
myclass
{
static
int
data;
public:
static
int
num;//声明
T
a;
myclass(T
t) :a(t)
{
num++;
data++;
}
static
void
run()
{
//this->a;
std::cout
<< data <<
std::endl;
std::cout
<< typeid(T).name()
<< "\n";
}
};
template<class
T>
int
myclass<T>::num
= 0;
template<class
T>
int
myclass<T>::data
= 0;
//静态变量,静态函数,同种类型的时候共享的静态变量
//类型不同,不共享静态变量
void
main1()
{
myclass<int>
my1(10);
myclass<double>
my2(10.9);
myclass<int>
my4(10);
myclass<int>::run();
myclass<int>::run();
myclass<int>::run();
my1.run();
myclass<double>::run();
std::cin.get();
//运行结果:
//2
//int
//2
//int
//2
//int
//1
//double
}
void
main()
{
myclass<int
> my1(10);
myclass<double
> my2(10.9);
myclass<std::string
> my3("1234");
myclass<int
> my4(10);
std::cout
<< &my1.num
<< std::endl;
std::cout
<< &my2.num
<< std::endl;
std::cout
<< &my3.num
<< std::endl;
std::cout
<< &my4.num
<< std::endl;
std::cout
<< &myclass<int
>::num <<
std::endl;
std::cout
<< &myclass<float
>::num <<
std::endl;
std::cin.get();
}
8.类模板之间的继承
#include<iostream>
#include
<string>
//模板类之间的继承
//类模板可以直接继承类模板,类型必须传递
//普通类继承类模板,需要明确类型实例化类模板
//类模板继承普通类,常规的操作方式
//类模板当作普通哦类,需要模板参数对类进行实例化
template<class
T>
//抽象模板类
class
myclass
{
public:
T
x;
myclass(T
t) :x(t)
{
}
virtual
void
print() = 0;
};
template<class
T>
class
newclass :public
myclass<T>
//继承必须明确类型
{
public:
T
y;
newclass(T
t1,
T
t2) :myclass(t1),
y(t2)
//调用父类的构造函数
{
}
void
print()
{
std::cout
<< x <<
"
" <<
y <<
std::endl;
}
};
void
main()
{
myclass<int>
*p =
new
newclass<int>(10,9);
p->print();
std::cin.get();
//运行结果是:10
9
}
当写成下面的函数时
void
main()
{
newclass<std::string>
my1("abc",
"xyz");
my1.print();
std::cin.get();
//运行结果是:abc
xyz
}
9.类模板继承普通类,普通类继承类模板等情况
#include<iostream>
#include
<string>
//模板类之间的继承
//类模板可以直接继承类模板,类型必须传递
//普通类继承类模板,需要明确类型实例化类模板
//类模板继承普通类,常规的操作方式
//类模板当作普通哦类,需要模板参数对类进行实例化
template<class
T>
//抽象模板类
class
myclass
{
public:
T
x;
myclass(T
t) :x(t)
{
}
virtual
void
print() = 0;
//可以带有纯虚函数
};
template<class
T>
class
newclass :public
myclass<T>
//继承必须明确类型
{
public:
T
y;
newclass(T
t1,
T
t2) :myclass(t1),
y(t2)
//调用父类的构造函数
{
}
void
print()
{
std::cout
<< x <<
"
" <<
y <<
std::endl;
}
};
//普通类
class
xyz
{
public:
int
x;
int
y;
int
z;
xyz(int
a,
int
b,
int
c) :x(a),
y(b),
z(c)
{
}
void
print()
{
std::cout
<< x <<
y <<
z;
}
};
template<class
T>
class
newxyz :public
xyz
{
public:
T
a;
//构造的时候给父类初始化
newxyz(T
t1,
int
a1,
int
b1,
int
c1) :xyz(a1,
b1,
c1),
a(t1)
{
}
void
print()
{
std::cout
<< "Ta=" <<
a <<
std::endl;
std::cout
<< x <<
y <<
z <<
std::endl;
}
};
/*普通类继承模板类的时候这是要确定类型*/
class
classrun :public
newxyz<int>
{
public:
int
d = 1000;
//下面的构造函数要确定类型
classrun(int
a2,
int
b2,
int
c2,
int
d2) :newxyz<int>(a2,
b2,
c2,
d2)
{
}
void
print()
{
std::cout
<< d <<
x <<
y <<
z <<
a;
}
};
void
main1()
{
classrun
run1(1, 2, 3, 4);
run1.print();
std::cin.get();
//运行结果是:10002341
}
void
main()
{
std::string
str1 =
"china";
newxyz<std::string>
new1(str1,
10, 90, 89);
new1.print();
std::cin.get();
//运行结果是:
//Ta=china
//109089
}
10.类模板与友元函数,类模板与友元类
#include
<iostream>
#include
<string>
#include
<vector>
template<class
T>
class
myclass;
template<class
T>
void
print(myclass<T>
& my,
T
t1);
template<class
T>
class
myclass
{
public:
//friend void print(myclass<T> & my,T t1);
//友元函数放在模板类的内部,实现重载
friend
void
print(myclass<T>
& my,
T
t1);
friend
myclass *
operator+(const
myclass<T>
& my1,
const
myclass<T>
& my2)
{
//下面的情况在栈上,用完了马山释放
//myclass class1
//堆上申请一个
myclass *
p =
new
myclass(my1.x
+ my2.x,
my1.y
+ my2.y);
return
p;
}
myclass(T
t1,
T
t2) :x(t1),
y(t2)
{
}
//访问私有需要友元
private:
T
x;
T
y;
};
template<class
T>
void
print(myclass<T>
& my,
T
t1)
{
std::cout
<< typeid(t1).name()
<< std::endl;
std::cout
<< my.x
<< "
" <<
my.y
<< std::endl;
}
using
namespace
std;
void
main()
{
myclass<int>
my1(19, 29);
vector<int>
v1;
vector<vector<int>>
v2;
vector<vector<vector<int>>>
v3;
//通过下面的方式对类型进行简写
using
VEC =
vector<vector<vector<int>>>;
//C++11简写
VEC
v4;//等价于三维int类型数据,模板
std::cin.get();
}
案例2
#include<iostream>
using
namespace
std;
//这里要声明模板类和友元函数
template<class
T>
class
Object;
template<class
T>
void
fun(const
Object<T>
&);
template<class
T>
class
Object
{
private:
T
_d;
public:
Object(T
d) :_d(d){}
//声明友元函数
friend
void
fun<T>(const
Object<T>
&);
};
template<class
T>
void
fun(const
Object<T>
& obj)
{
cout <<
obj._d
<< endl;
}
int
main()
{
Object<double>
obj(111.4);
fun<double>(obj);
std::cin.get();
return 0;
//运行结果:111.4
}
类模板与友元类
#include
<iostream>
using
namespace
std;
//定义友元类和友元函数
template<class
T>
class
myclass;
template<class
T>
void
print(const
myclass<T>
&);
template<class
T>
class
runclass;
template<class
T>
class
myclass
{
private:
T
x;
T
y;
public:
myclass(T
t1,
T
t2) :x(t1),
y(t2)
{
}
//友元必须类名
friend
void
print<T>(const
myclass<T>
&);
friend
class
runclass<T>;
};
template<class
T>
void
print(const
myclass<T>
&my)
{
std::cout
<< my.x
<< "
" <<
my.y
<< std::endl;
}
template<class
T>
class
runclass
{
public:
void
print(const
myclass<T>
& my)
{
std::cout
<< my.x
<< "
" <<
my.y
<< std::endl;
}
};
void
main()
{
myclass<int>
my1(19, 29);
myclass<int>
my2(11,1);
print(my2);
runclass<int>
runclass1;
runclass1.print(my1);
std::cin.get();
//运行结果:
//11
1
//19
29
}
11.类模板当作模板参数
#include<iostream>
#include
<string>
using
namespace
std;
//类模板当作一个类的参数
//设计STL的时候用到
template<class
T>
class
ren
//一个通用的类的类模板
{
public:
T
name;
ren(T
t) :name(t)
{
}
};
//使用类模板当作模板参数的类
template<template<class
T>
class
T1>
class
people
{
public:
T1<string>
t1x =
"123123";//T1必须实例化
。必须结合
T1<string>
num =
"ABC";
//等价于ren类型
//T1 x
people(T1<string>
&t1)
{
std::cout
<< typeid(t1).name()
<< std::endl;
std::cout
<< typeid(T1).name()
<< std::endl;
std::cout
<< t1.name
<< std::endl;
t1x =
t1;
num =
t1;
}
};
void
main()
{
ren<string>
ren1("hello8848");//基本数据类型
people<ren>
people1(ren1);
//嵌套的类模板
std::cout
<< people1.t1x.name
<< std::endl;
std::cout
<< people1.num.name
<< std::endl;
std::cout
<< ren1.name
<< std::endl;
std::cin.get();
}
运行结果:
12.类包装器
#include
<iostream>
//类包装器,实现一个操作接口,操作多个类的方法
template<typename
T,typename
F>
T
run(T
t,
F
f)
{
return
f(t);
}
int
add(int
num)
{
return
num + 10;
}
class
myclass
{
public:
int
num;
myclass(int
data) :num(data)
{
}
int operator ()(int
X)
{
return
X*num;
}
};
class
myclassA
{
public:
int
num;
myclassA(int
data) :num(data)
{
}
int operator ()(int
X)
{
std::cout
<< "A\n";
return
X -
num;
}
};
void
main1()
{
myclass
my1(5);
//函数作为参数
std::cout
<< run(101,
my1) <<
std::endl;
//函数作为参数,下面的重载调用了()操作符
std::cout
<< run(101,
myclassA(51)) <<
std::endl;
std::cin.get();
//运行结果是:
//505
//A
//50
}
void
main()
{
auto
num = 100;
auto
func =
add;
//调用add函数
std::cout
<< run(num,
add) <<
std::endl;
std::cin.get();
//运行结果:110
}
13.类嵌套
#include<iostream>
//类的嵌套
class
myclass
{
public:
class
newclass
{
public:
int
num;
} new1;
};
class
newnewclass :public
myclass
{
};
void
main1()
{
newnewclass
newx;
newx.myclass::new1.num
= 10;
std::cout
<< newx.new1.num;
std::cin.get();
//运行结果:10
}
void
main()
{
myclass
myclass1;
myclass1.new1.num
= 19;
std::cout
<< myclass1.new1.num;
std::cin.get();
//运行结果:19
}
14.类模板嵌套
#include
<iostream>
template<class
T>
class
myclass
{
public:
class
newclass
{
public:
int
num;
} new1;
//定义的方式
newclass
new2;
template<class
V>
class
runclass
{
public:
V
v1;
};//类模板后面不可以直接初始哈
runclass<T>
t1;
runclass<double>
t2;
};
void
main()
{
myclass<int>
my1;
my1.new1.num
= 10;
//给嵌套类中的变量赋值
my1.t1.v1
= 12;
//给嵌套类中的变量赋值
my1.t2.v1
= 12.9;
std::cout
<< my1.t1.v1
<< "\n" <<
my1.t2.v1;
std::cin.get();
//运行结果:
//12
//12.9
}