类模板(泛型编程)
泛型编程:(方法一致,但数据类型不确定)由函数模板或者类模板来完成的。
函数模板
template<typename T>
函数定义;
类模板:定义相同的操作,拥有不同数据类型的成员属性。
template<typename T>
class 类名
{
//属性
确定类型
泛型
};
类模板继承
template<typename T>
class parent
{
};
//注意:
1、如果子类不是类模板,则父类必须声明类模板的数据类型
2、子类必须初始化父类(父类的构造器)
3、如果子类模板,要么指定父类的类型,要么用子类的泛型来指定父类。
在子类中初始化父类部分时,由构造器来构造器。调用构造器需要指定类型。
clas child:<继承方式> parent<类型>
{
...
child():parent<类型>(..)
...
};
1、类模板实例化
类<类型> 对象;
2、类外定义函数:
template<typename T>
类名<T>::方法(...)
{
}
3、二次编译:见代码Complex.cpp代码(重载输出运算符)
解决:前置声明。先在类定义的上面声明该函数为模板函数。
1、类的前置声明(类模板)
template<typename T>
class 类名;
2、友元函数(模板函数)的前置声明
template<typename T>
函数声明;
3、声明友元函数时,增加泛型支持。
friend ostream& operator<< <T>(ostream& d2,Complex<T> &);
类模板的使用 .
#include<iostream>
#include<string.h>
using namespace std;
class people
{
public:
//无参构造
people(){}
people(const char* n,char s):name(n),sex(s)
{
}
friend ostream& operator<<(ostream&,people&);
protected:
string name;//姓名
char sex;
};
//重载运算符--友元函数
ostream& operator<<(ostream& output,people& p)
{
output<<p.name<<" "<<p.sex<<" ";
return output;
}
//定义数组类--泛型编程(类模板)
template <typename T>
class Array
{
public:
//构造器
Array(T b[],int ilen)//局部变量优先
{
this->ilen=ilen;
memcpy(this->buf,b,ilen*sizeof(T));//内存拷贝
}
void show()
{
int i=0;
while(i<this->ilen)
{
//基本类型,如果是复杂类型则重载
cout<<this->buf[i++]<<" ";
}
cout<<endl;
}
private:
int ilen;//长度(整型)
T buf[100];//泛型
};
//类继承:从父类派生出子类(拷贝父类一份给子类)
int main()
{
/******************基本类型************************/
//实例化--整型
int buf[10]={1,2,3,4,5};
Array<int> a(buf,5);
a.show();
//浮点型
float buf1[10]={3.14,7.0,8.9};
Array<float> b(buf1,3);
b.show();
//复杂类型
people buf2[3]={people("lifei,",'m'),people("lj",'m'),people("zzs",'w')};
Array<people> c(buf2,3); //Array(people* ,int)
//构造器
c.show();
}
在复杂类型的时候 T buf[100]; 的时候 , 因为此时的 T 是复杂类型 相当于==> people buf[100] ; 所以此时的 T buf[100] ; 会调用到 people 的无参构造 , 所以切记要为people 添加一个无参构造 , 在输出show的时候 , 因为是复杂类型 ,所以需要对输出运算符进行重载输出 , 不然会输出报错!
子类继承父类模板的使用 :
子类继承父类的模板类 , 子类需要为继承的父类添加类型 , 可以自己定义类型 , 也可以定义子类的泛型 .
#include<iostream>
#include<string>
using namespace std;
//类模板:
template<typename T>
class people
{
public:
//有参构造:如果有参被定义,则无参构造不会被生成
people(){}
people(T i):id(i){}
protected:
T id;
};
//子类:是类型模板
template<typename T1>
class worker:public people<T1>//people要么自己指定类型,要么用子类的泛型
{
public:
//无参
worker():people<T1>()
{
}
worker(T1 id,T1 g,int s):people<T1>(id)
{
this->g=g;
this->score=s;
}
void show()
{
cout<<g<<" "<<score<<" "<<id<<endl;
}
protected:
T1 g;
int score;
};
/*
//继承:子类不是类模板
class worker:public people<int>
{
public:
//
worker():people()
{
}
worker(int i,const char* n):people(i),name(n)
{
}
void show()
{
cout<<"ID:"<<this->id<<" "<<this->name<<endl;
}
protected:
string name;
};
*/
int main()
{
/*
//实例化:
people<int> a;
worker w(1001,"llllllll");
w.show();
*/
worker<int> w(1001,4,100);
w.show();
return 0;
}
类外实现方法的定义 :
#include<iostream>
using namespace std;
//前置声明:告诉编译器此函数为模板函数
template<typename T>
class Complex;//声明类
template<typename T>
ostream& operator<<(ostream&,Complex<T> &);
//类模板
template<typename T>
class Complex
{
public:
Complex(T d1,T d2);
//友元
friend ostream& operator<<<T>(ostream&,Complex<T> &);
protected:
T a;
T b;
};
//类外实现方法的定义
template<typename T>
Complex<T>::Complex(T d1,T d2):a(d1),b(d2)
{
}
//重载输出 Complex是泛型 函数模板
template<typename T1>
ostream& operator<<(ostream& output,Complex<T1> &c)
{
output<<c.a<<" "<<c.b<<" ";
}
int main()
{
//实例化
Complex<float> c(1,2);
cout<<c<<endl;
return 0;
}