C++面向对象程序设计之模板

C++面向对象程序设计之模板


1、提高程序可重用性的两种办法:

继承;
泛型程序设计(模板)

2、模板的实例化:编译器根据模板自动生成函数的过程称为模板的实例化。

一、函数的模板

3、函数模板的形式:

template<class 类型参数1,class 类型参数2,...>
返回值类型  模板名(形参表){
函数体;
};
example:
template<class T>
void Swap<T & x,T & y>
{
T temp=x;
x=y;
y=temp;
}

在这里插入图片描述

4、函数模板的一些特点

函数的模板中可以有不止一个类型参数

template <class T1, class T2>
T2 print(T1 arg1,T2 arg2)
{
cout<<arg1<<" "<<arg2<<endl;
return arg2;
}

example

template <class T>
T MaxElement(T a[],int size)
{
T tmpMax=a[0];
for(int i=1;i<size;++i)
if(tmpMax<a[i])
tmpMax=a[i];
return tmpMax;
}

函数的模板可以重载,只要它们的形参表或类型参数表不同即可。
在这里插入图片描述

函数模板和函数的次序:

在有多个函数和函数模板名字相同的情况下,编译器如下处理一条函数调用语句
1、先找参数完全匹配的普通函数(非由模板实例化得到的函数)
2、再找参数完全匹配的模板函数
3、再找实参数经过自动类型转换后能够匹配的普通函数。
4、上面的都找不到,则报错。

注意:在匹配模板函数时,不进行类型自动转换

template<class T>
T myFunction(T arg1,T arg2)
{
cout<<arg1<<" "<<arg2<<"\n";
return arg1;

}
myFunction(5,7);//ok
myFunction(5.8,8.4);//ok
myFunction(5,8.4);//error

综合实例:

#include<iostream>
using namespace std;
template<class T,class Pred>
void Map(T s,T e,T x,Pred op)
{
    for(;s!=e;++s,++x)
    {
            *x=op(*s);
    }
}
int Cube(int x)
{
    return x*x*x;
}
double Square(double x){
        return x*x;
}
int a[5]={1,2,3,4,5},b[5];
double d[5]={1.1,2.1,3.1,4.1,5.1},c[5];
int main(){
    Map(a,a+5,b,Square);
    for(int i=0;i<5;++i)
        cout<<b[i]<<",";
    cout<<endl;

    Map(a,a+5,b,Cube);
    for(int i=0;i<5;++i)
        cout<<b[i]<<",";
    cout<<endl;
    Map(d,d+5,c,Square);
    for(int i=0;i<5;++i)
        cout<<c[i]<<",";
    cout<<endl;
        return 0;
}

二、类的模板

2.1 主要目标:定义一批相似的类,可以通过定义类模板然后由类模板生成不同的类。

2.2 类模板定义的两种方式:

template<class 类型参数为,class 类型参数2,......>//类型参数表
class 类模板名
{
成员函数和成员变量;
};
template<typename 类型参数为,typename 类型参数是,......>//类型参数表
class 类模板名
{
成员函数和成员变量;
};

其实typename和class是等价的,用那个都行。

2.3 类模板中成员函数的写法:

template<class 类型参数1,class 类型参数2,...>//类型参数表
返回值类型 类模板名 <类型参数名列表>::成员函数名(形参数表)
{
................
}

2.4 类模板定义对象的写法:

类模板名<真实类型参数表> 对象名(构造函数实参表);

example

template<class T1,class T2>
class Pair
{
public:
T1 key;
T2 value;
Pair(T1 k,T2 v):key(k),value(v){};
bool operator < (const Pair<T1,T2> & p) const
{
return key<p.key;
}
};
int main()
{
Pair<string,int>student("Tom",19);
cout<<student.key<<" "<<student.value;
return 0;
}

用类模板定义对象

编译器由类模板生成类的过程叫类模板的实例化。

由类模板实例化得到的类,叫模板类。

同一个类模板的两个模板类是不兼容的。

Pair<string,int>*p;
Pair<string,double>a;
p=&a;//wrong

2.5 函数模板作为类模板成员

#include<iostream>
using namespace std;
template <class T>
class A
{
public:
    template<class T2>
        void Func(T2 t){cout<<t;}//成员函数模板
};
int main()
{
    A<int>a;
    a.Func('K');//成员函数模板被实例化
    a.Func("hello");//
    return 0;
}

2.6 类模板与非类型参数

类模板的“<类型参数表>”中可以出现非类型参数

template <clas T,int size>
Class CArray{
T array[size];
public:
void Print()
{
for(int i=0;i<size;++i)
cout<<array[i]<<endl;
}
};
CArray<double,40>a2;
CArray<int,50>a3;

三、类模板与派生

1、类模板派生的四种方式:

//类模板从类模板派生;
//类模板从模板类派生;
//类模板从普通类派生;
//普通类从模板类派生;

1.1 类模板从类模板派生

template <class T1,class T2>
class A{
T1 v1;T2 v2;
};
template <class T1,class T2>
class B:public A<T2,T1>{
T1 v3; T2 v4;
}
template<class T>
class C:public B<T,T>{
T v5;
}
int main()
{
    B<int,double> obj1;
    C<int> obj2;
    return 0;
}

1.2 类模板从类模板派生

template <class T1,class T2>
class A{
T1 v1;T2 v2;
};
template <class T>
class B:public A<int,double>{
T v;
};
int main(){
    B<char> obj1;//自动生成两个模板类:A<int,double>和B<char>
    return 0;
}

1.3类模板从普通类派生

class A{
    int v1;
};
template<class T>
   class B:public A{//所有从B实例化得到的类,都以A为基类
       T v;
   };
int main()
{
    B<char> obj1;
    return 0;
}

1.4 普通类从模板类派生

template <class T>
class A{
T v1;
int n;
};
class B:public A<int>{
    double v;
};
int main(){
    B obj1;
    return 0;
}

四、类模板与友元

函数、类、类的成员函数作为类模板的友元;
函数模板作为类模板的友元;
函数模板作为类的友元;
类模板作为类模板的友元;

4.1 函数、类、类的成员函数作为类模板的友元

void Func1(){}
class A{};
class B{
public:
void Func(){}
};
template <class T>
class Tmpl
{
friend void Func1();
friend class A;
friend void B::Func();
};//任何从Tmpl1实例化来的类,都有以上三个友元

4.2 函数模板作为类模板的友元

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纷繁中淡定

你的鼓励是我装逼的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值