首页 > 代码库 > 类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器


1.第一个最简单的类模板案例

#include"mainwindow.h"

#include<QApplication>

#include<QPushButton>

#include<QLabel>

 

template<classT>   

classrun

{

public:

   Tw;

   voidshow()

   {

       w.show();

   }

   voidsettext()

   {

       w.setText("A");

   }

};

 

intmain(intargc,char*argv[])

{

   QApplicationa(argc,argv);

 

   run<QPushButton>run1;

   run1.show();

   run1.settext();

 

   returna.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;
}
  1. 多种类型的类模板
案例:

#include<iostream>

#include<string>

 

//定义两种数据类型的类模板

//STL数据结构,算法,适合任何类型

 

//定义两种数据类型的类模板

template<classT1,classT2>

classmyclass

{

public:

   T1t11;

   T2t22;

   myclass(T1t111,T2t222) :t11(t111),t22(t222)

   {

   }

 

   voidprint()

   {

       std::cout << t11 <<" " <<t22 <<std::endl;

   }

};

 

voidmain()

{

   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

#pragmaonce//只包含一次,只是针对VS下的

 

//类模板可以有一个默认的值

template<classT =int>

classmyArray

{

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" //类模板的成员函数没有实例化,不会自动找到,需要手动包含

 

usingnamespacestd;

 

voidmain1()

{

   myArray<double>my1;

   myArray<>my2;//C++11的新功能(如果有默认类型了,这时候类型可以为空)

 

   std::cin.get();

   //结果输出

   //构造double

   //构造int

}

 

voidmain()

{

   array<string, 5>strarray = {"calc","mspaint","notepad","tasklist","pause" };

   for (inti = 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

#pragmaonce

template<classT,intn>

classArray

{

public:

   Array();

   Array(intlength);

   ~Array();

   intsize();

   Tget(intnum);

   T & operator [](intnum);//重载[]

   voidset(Tdata,intnum);

public:

   T *pt;

};

Array.cpp

#include"Array.h"

 

template<classT,intn>//int n不可以修改,不是类的内部成员

Array<T,n>::Array()

{

   this->pt = newT[n];

}

 

/*****************************

 *初始化length个长度的数组

 *****************************/

template<classT,intn>//每一个函数都必须模板

Array<T,n>::Array(intlength)

{

   this->pt = newT[length];

}

 

/*****************************

 *析构数组

 *****************************/

template<classT,intn>//每一个函数都必须模板

Array<T,n>::~Array()

{

   //n = 0;

   delete[]this->pt;

}

 

/*****************************

*获得Array的大小

*****************************/

template<classT,intn>

intArray<T,n>::size()

{

   returnn;

}

 

/*****************************

*获得第n个元素

*****************************/

template<classT,intn>//每一个函数都必须模板

TArray<T,n>::get(intnum)//num是数组的下标

{

   if (num >= n ||num < 0)//报错

   {

       //异常

   }

   else

   {

       return *(this->pt + num);

   }

}

 

/*****************************

 *设置第i个元素的值

 *****************************/

template<classT,intn>//每一个函数都必须模板

voidArray<T,n>::set(Tdata,intnum)

{

   if (num < 0 || num >=n)

   {

   }

   else

   {

       *(pt +num) =data;

   }

}

 

/*****************************

*重载[]

*****************************/

template<classT,intn>//每一个函数都必须模板

T&Array<T,n>::operator [](intnum)

{

   if (num < 0 || num >=n)

   {

   }

   else

   {

       return *(pt + num);

   }

}

测试Array的主函数:

#include<iostream>

#include<string>

#include"Array.h"

#include"Array.cpp"

 

usingnamespacestd;

 

voidmain1()

{

   Array<int, 5> myarray;

   for (inti = 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<classT,intn>//类模板作为参数,类型无比明确

voidprint(Array<T,n> &myArray)

{

   for (inti = 0;i <myArray.size();i++)

   {

       std::cout << myArray[i] << std::endl;

   }

}

 

voidmain()

{

   Array<int, 5> myarray;

   //调用size()函数,求Array中的大小

   for (inti = 0;i <myarray.size();i++)

   {

       myarray.set(i,i);

   }

   //通过函数模板实现打印array中的数据

   print(myarray);

 

   std::cin.get();

   //打印结果是:

   //0

   //1

   //2

   //3

   //4

}

5.友元类类模板

#include<iostream>

 

//友元类必须声明类的存在,

//需要声明友元类,必须要与类型相关

template<classT>classmyclass;

template<classT>classrunclass;

 

template<classT>

classmyclass

{

public:

   myclass(Tt) :x(t){}

   friendclassrunclass<T>;//声明友元类

private:

   Tx;//模板友元类

};

 

template<classT>

classrunclass

{

public:

   voidprint(constmyclass<T> & my)

   {

       //直接访问传递进来的类的私有变量

       std::cout << my.x << std::endl;

   }

};

voidmain()

{

   myclass<double>my1(19.8);

   //myclass中定义的友元类

   runclass<double>run1;

   run1.print(my1);

 

   std::cin.get();

}

6.友元函数

#include<iostream>

template <classT>classmyclass;  //这里一定要声明这个友元类

template <classT>voidprintA(myclass<T>my);

 

template <classT>

classmyclass

{

public:

   myclass(Tt) :x(t)

   {

   }

   friendvoidprint(myclass<T>my)

   {

       std::cout << my.x << std::endl;

   }

   //友元函数如果在外部,第一声明要加类型T

   //必须要声明类还有函数

   friendvoidprintA<T>(myclass<T>my);

 

private:

   Tx; //模板友元类

   //int y;访问与T无关的类型,普通友元类

};

 

template <classT>

voidprintA(myclass<T>my)

{

   std::cout << my.x << std::endl;

}

 

voidmain()

{

   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<classT>

classmyclass

{

   staticintdata;

public:

   staticintnum;//声明

   Ta;

   myclass(Tt) :a(t)

   {

       num++;

       data++;

   }

   staticvoidrun()

   {

       //this->a;

       std::cout << data <<std::endl;

       std::cout << typeid(T).name() << "\n";

   }

};

 

template<classT>

int myclass<T>::num = 0;

template<classT>

int myclass<T>::data = 0;

 

//静态变量,静态函数,同种类型的时候共享的静态变量

//类型不同,不共享静态变量

voidmain1()

{

   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

}

 

voidmain()

{

   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<classT> //抽象模板类

classmyclass

{

public:

   Tx;

   myclass(Tt) :x(t)

   {

   }

   virtualvoidprint() = 0;

};

 

template<classT>

classnewclass :publicmyclass<T>//继承必须明确类型

{

public:

   Ty;

   newclass(Tt1,Tt2) :myclass(t1),y(t2)//调用父类的构造函数

   {

   }

   voidprint()

   {

       std::cout << x <<"  " <<y <<std::endl;

   }

};

 

voidmain()

{

   myclass<int> *p =newnewclass<int>(10,9);

   p->print();

 

   std::cin.get();

   //运行结果是:10   9

}

 

当写成下面的函数时

voidmain()

{

   newclass<std::string>my1("abc","xyz");

   my1.print();

 

   std::cin.get();

   //运行结果是:abc  xyz

}

9.类模板继承普通类,普通类继承类模板等情况

#include<iostream>

#include<string>

//模板类之间的继承

 

//类模板可以直接继承类模板,类型必须传递

//普通类继承类模板,需要明确类型实例化类模板

//类模板继承普通类,常规的操作方式

//类模板当作普通哦类,需要模板参数对类进行实例化

 

template<classT> //抽象模板类

classmyclass

{

public:

   Tx;

   myclass(Tt) :x(t)

   {

   }

   virtualvoidprint() = 0; //可以带有纯虚函数

};

 

template<classT>

classnewclass :publicmyclass<T>//继承必须明确类型

{

public:

   Ty;

   newclass(Tt1,Tt2) :myclass(t1),y(t2)//调用父类的构造函数

   {

   }

   voidprint()

   {

       std::cout << x <<"  " <<y <<std::endl;

   }

};

 

//普通类

classxyz

{

public:

   intx;

   inty;

   intz;

   xyz(inta,intb,intc) :x(a),y(b),z(c)

   {

   }

   voidprint()

   {

       std::cout << x <<y <<z;

   }

};

 

template<classT>

classnewxyz :publicxyz

{

public:

   Ta;

   //构造的时候给父类初始化

   newxyz(Tt1,inta1,intb1,intc1) :xyz(a1,b1,c1),a(t1)

   {

       

   }

   voidprint()

   {

       std::cout << "Ta=" <<a <<std::endl;

       std::cout << x <<y <<z <<std::endl;

   }

};

 

/*普通类继承模板类的时候这是要确定类型*/

classclassrun :publicnewxyz<int>

{

public:

   intd = 1000;

   //下面的构造函数要确定类型

   classrun(inta2,intb2,intc2,intd2) :newxyz<int>(a2,b2,c2,d2)

   {

       

   }

   voidprint()

   {

       std::cout << d <<x <<y <<z <<a;

   }

};

 

voidmain1()

{

   classrunrun1(1, 2, 3, 4);

   run1.print();

   std::cin.get();

   //运行结果是:10002341

}

 

voidmain()

{

   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<classT>classmyclass;

template<classT>voidprint(myclass<T> & my,Tt1);

 

template<classT>

classmyclass

{

public:

   //friend void print(myclass<T> & my,T t1);

   //友元函数放在模板类的内部,实现重载

   friendvoidprint(myclass<T> & my,Tt1);

   friendmyclass *operator+(constmyclass<T> & my1,constmyclass<T> & my2)

   {

       //下面的情况在栈上,用完了马山释放

       //myclass class1

 

       //堆上申请一个

       myclass *p =newmyclass(my1.x + my2.x,my1.y + my2.y);

       returnp;

   }

 

   myclass(Tt1,Tt2) :x(t1),y(t2)

   {

       

   }

   //访问私有需要友元

private:

   Tx;

   Ty;

};

 

template<classT>

voidprint(myclass<T> & my,Tt1)

{

   std::cout << typeid(t1).name() << std::endl;

   std::cout << my.x << "  " <<my.y << std::endl;

}

 

usingnamespacestd;

voidmain()

{

   myclass<int>my1(19, 29);

   vector<int>v1;

   vector<vector<int>>v2;

   vector<vector<vector<int>>>v3;

   //通过下面的方式对类型进行简写

   usingVEC =vector<vector<vector<int>>>; //C++11简写

   VECv4;//等价于三维int类型数据,模板

 

   std::cin.get();

}

案例2

#include<iostream>

usingnamespacestd;

//这里要声明模板类和友元函数

template<classT>classObject;

template<classT>voidfun(constObject<T> &);

 

template<classT>

classObject

{

private:

   T_d;

public:

   Object(Td) :_d(d){}

   //声明友元函数

   friendvoidfun<T>(constObject<T> &);

};

 

template<classT>

voidfun(constObject<T> & obj)

{

   cout <<obj._d << endl;

}

 

intmain()

{

   Object<double>obj(111.4);

   fun<double>(obj);

   std::cin.get();

   return 0;

   //运行结果:111.4

}

类模板与友元类

#include<iostream>

usingnamespacestd;

 

//定义友元类和友元函数

template<classT>classmyclass;

template<classT>voidprint(constmyclass<T> &);

template<classT>classrunclass;

 

template<classT>

classmyclass

{

private:

   Tx;

   Ty;

public:

   myclass(Tt1,Tt2) :x(t1),y(t2)

   {

   }

   //友元必须类名

   friendvoidprint<T>(constmyclass<T> &);

   friendclassrunclass<T>;

};

 

template<classT>

voidprint(constmyclass<T> &my)

{

   std::cout << my.x << "  " <<my.y << std::endl;

}

 

template<classT>

classrunclass

{

public:

   voidprint(constmyclass<T> & my)

   {

       std::cout << my.x << " " <<my.y << std::endl;

   }

};

 

voidmain()

{

   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>

usingnamespacestd;

 

//类模板当作一个类的参数

//设计STL的时候用到

 

template<classT>

classren //一个通用的类的类模板

{

public:

   Tname;

   ren(Tt) :name(t)

   {

   }

};

 

//使用类模板当作模板参数的类

template<template<classT>classT1>

classpeople

{

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;

   }

};

 

voidmain()

{

   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<typenameT,typenameF>

Trun(Tt,Ff)

{

   returnf(t);

}

 

intadd(intnum)

{

   returnnum + 10;

}

 

classmyclass

{

public:

   int num;

   myclass(intdata) :num(data)

   {

   }

   int operator ()(intX)

   {

       returnX*num;

   }

};

 

classmyclassA

{

public:

   int num;

   myclassA(intdata) :num(data)

   {

   }

   int operator ()(intX)

   {

       std::cout << "A\n";

       returnX -num;

   }

};

 

voidmain1()

{

   myclassmy1(5);

   //函数作为参数

   std::cout << run(101,my1) <<std::endl;

   //函数作为参数,下面的重载调用了()操作符

   std::cout << run(101,myclassA(51)) <<std::endl;

   std::cin.get();

   //运行结果是:

   //505

   //A

   //50

}

 

voidmain()

{

   autonum = 100;

   autofunc =add;

   //调用add函数

   std::cout << run(num,add) <<std::endl;

 

   std::cin.get();

   //运行结果:110

}

13.类嵌套

#include<iostream>

 

//类的嵌套

classmyclass

{

public:

   classnewclass

   {

   public:

       intnum;

   } new1;

};

 

classnewnewclass :publicmyclass

{

};

 

voidmain1()

{

   newnewclassnewx;

   newx.myclass::new1.num = 10;

 

   std::cout << newx.new1.num;

   std::cin.get();

   //运行结果:10

}

 

voidmain()

{

   myclassmyclass1;

   myclass1.new1.num = 19;

   std::cout << myclass1.new1.num;

   std::cin.get();

   //运行结果:19

}

14.类模板嵌套

#include<iostream>

 

template<classT>

classmyclass

{

public:

   classnewclass

   {

   public:

       intnum;

   } new1; //定义的方式

   newclassnew2;

 

   template<classV>

   classrunclass

   {

   public:

       Vv1;

   };//类模板后面不可以直接初始哈

   runclass<T>t1;

   runclass<double>t2;

};

 

voidmain()

{

   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

}

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器