模板的超详细的案例讲解(上)


c++提供了函数模板(functiontemplate.)所谓函数模板,实际上是建立一个通用函 数,其函数类型和形参类型不具体制定,用一个虚拟的类型来代表。这个通用函数 就成为函数模板。凡是函数体相同的函数都可以用这个模板代替,不必定义多个函 数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板 中的虚拟类型,从而实现不同函数的功能。c++提供两种模板机制:函数模板和类 模板 类属-类型参数化,又称参数模板 总结: 模板把函数或类要处理的数据类型
参数化,表现为参数的多态性,成为类属。 模板用于表达逻辑结构相同,但具体 数据元素类型不同的数据对象的通用行为。

c++特点:封装、继承、多态
c++特点:面向对象编程、泛型编程

1、函数模板

在这里插入图片描述
春来我不先开口,哪个虫儿敢吱声。

案例:

//函数模板 template是关键字
//class 和 typename一样的
//T 系统自动推导 或 用户指定
template<typename T>
void mySwap(T &a,T &b)
{
    T tmp;
    tmp = a;
    a = b;
    b = tmp;
}
void test02()
{
    int data1 = 10,data2=20;
    cout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;
    mySwap(data1,data2);//自动推导出T为int
    cout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;


    char data3 = 'a',data4='b';
    cout<<"data3 = "<<data3<<", data4 = "<<data4<<endl;
    mySwap(data3,data4);//自动推导出T为char
    cout<<"data3 = "<<data3<<", data4 = "<<data4<<endl;
}
int main(int argc, char *argv[])
{
    test02();
    return 0;
}

运行结果:
在这里插入图片描述

2、用户指定T的类型

void test03()
{
    int data1 = 10,data2=20;
    cout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;
    //用户显示指定 T为int
    mySwap<int>(data1,data2);
    cout<<"data1 = "<<data1<<", data2 = "<<data2<<endl;
}

3、函数模板 和 普通函数的区别

案例:

void mySwap(int &a,int &b)
{
    cout<<"普通函数"<<endl;
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
}

template<typename T>
void mySwap(T &a,T &b)
{
    cout<<"函数模板"<<endl;
    T tmp;
    tmp = a;
    a = b;
    b = tmp;
}
void test01()
{
    int data1 = 10,data2 = 20;
    //函数模板和普通函数 都识别  优先选择普通函数
    mySwap(data1,data2);

    //函数模板和普通函数 都识别  选择函数模板 加<>
    mySwap<>(data1,data2);
}

运行结果:
在这里插入图片描述

案例2:函数模板的调用时机

函数模板可以重载

#include <iostream>

using namespace std;

void mySwap(int a,int b)
{
    cout<<"普通函数"<<endl;
}

template<typename T>
void mySwap(T a,T b)
{
    cout<<"函数模板"<<endl;
}
void test01()
{
    int a = 10;
    char b = 'b';

    //默认优先选择普通函数
    mySwap(a,a);

    //选择函数模板
    mySwap<>(a,a);

    //函数模板 的参数类型 不能自动类型转换
    //普通函数 的参数类型 不能自动类型转换
    mySwap(a,b);//选择普通函数


    //用户 指定T的类型
    mySwap<int>(a,b);//选择函数模板
}
int main(int argc, char *argv[])
{
    test01();
    return 0;
}

运行结果:
在这里插入图片描述

4、函数模板的课堂练习

//排序
template<typename T>
void  myPintArrayTemplate(T *arr, int len)
{
    int i=0;
    for(i=0;i<len;i++)
        cout<<arr[i]<<" ";
    cout<<endl;
}

template<typename T>
void mySortArrayTemplate(T *arr, int len)
{
    int i=0,j=0;
    for(i=0;i<len-1; i++)
    {
        int min = i;
        for(j=min+1; j<len;j++)
        {
            if(arr[min] > arr[j])
                min = j;
        }

        if(min != i)
        {
            T tmp = arr[min];
            arr[min] = arr[i];
            arr[i] = tmp;
        }
    }
    return;
}
int main(int argc, char *argv[])
{
    char str[]="hello template";
    int str_len = strlen(str);
    int arr[]={5,3,4,7,8,9,1,6,10};
    int arr_len = sizeof(arr)/sizeof(arr[0]);

    //用函数模板遍历数组
    myPintArrayTemplate(str, str_len);
    myPintArrayTemplate(arr, arr_len);

    //用函数模板对数组排序
    mySortArrayTemplate(str,str_len);
    mySortArrayTemplate(arr, arr_len);

    //用函数模板遍历数组
    myPintArrayTemplate(str, str_len);
    myPintArrayTemplate(arr, arr_len);

    return 0;
}

运行结果:
在这里插入图片描述

5、函数模板具体化

#include <iostream>

using namespace std;

class Person
{
    friend  ostream& operator<<(ostream &out, Person &ob);
public:
    int a;
    int b;
public:
    Person(int a,int b)
    {
        this->a = a;
        this->b = b;
        cout<<"构造函数"<<endl;
    }
    ~Person()
    {
        cout<<"析构函数"<<endl;
    }
    
    //方法2:重载>运算符 推荐
    bool operator>(const Person &ob)
    {
        return (this->a > ob.a);
    }
};

ostream& operator<<(ostream &out, Person &ob)
{
   out<<"a = "<<ob.a<<", b = "<<ob.b<<endl;
   return out;
}
template<typename T>
T& myMax(T &a, T &b)
{
    return a>b ? a:b;

}
//方法1:提供函数模板 具体化
#if 0
template<> Person& myMax<Person>(Person &ob1, Person &ob2)
{
    return ob1.a>ob2.b ? ob1:ob2;
}
#endif

void test01()
{
    int data1=10,data2=20;

    cout<<myMax(data1,data2)<<endl;

    Person ob1(10,20);
    Person ob2(100,200);

    cout<<myMax(ob1,ob2)<<endl;
}
int main(int argc, char *argv[])
{
    test01();
    return 0;
}

运行结果:
在这里插入图片描述

6、类模板

#include <iostream>
#include<string>
using namespace std;
//类模板
template<class T1, class T2>
class Data
{
private:
    T1 name;
    T2 num;
public:
    Data(T1 name, T2 num)
    {
        this->name = name;
        this->num = num;
        cout<<"有参构造"<<endl;
    }
    ~Data()
    {
        cout<<"析构函数"<<endl;
    }
    void showData(void)
    {
        cout<<"name="<<this->name<<", num="<<this->num<<endl;
    }
};

void test01()
{
    //Data ob1("德玛西亚",100);//err 类模板不允许 自动推导
    Data<string,int> ob1("德玛西亚",100);
    ob1.showData();

    Data<int,string> ob2(200, "提莫");
    ob2.showData();

    Data<int,int> ob3(100,200);
    ob3.showData();

    Data<string,string> ob4("小炮","德玛");
    ob4.showData();
}
int main(int argc, char *argv[])
{
    test01();
    return 0;
}

运行结果:
在这里插入图片描述

7、类模板作为函数的参数(了解)

#include <iostream>
#include<string>
using namespace std;
//类模板
template<class T1, class T2>
class Data
{
    friend void addData(Data<string,int> &ob);
private:
    T1 name;
    T2 num;
public:
    Data(T1 name, T2 num)
    {
        this->name = name;
        this->num = num;
        cout<<"有参构造"<<endl;
    }
    ~Data()
    {
        cout<<"析构函数"<<endl;
    }
    void showData(void)
    {
        cout<<"name="<<this->name<<", num="<<this->num<<endl;
    }
};

void test01()
{
    //Data ob1("德玛西亚",100);//err 类模板不允许 类型推导
    Data<string,int> ob1("德玛西亚",100);
    ob1.showData();

    Data<int,string> ob2(200, "提莫");
    ob2.showData();

    Data<int,int> ob3(100,200);
    ob3.showData();

    Data<string,string> ob4("小炮","德玛");
    ob4.showData();
}

void addData(Data<string,int> &ob)
{cout<<"-普通函数---"<<endl;
    ob.name += "_vip";
    ob.num += 2000;
    return;
}

void test02()
{
    Data<string,int> ob("德玛西亚",18);
    addData(ob);
    ob.showData();
}
int main(int argc, char *argv[])
{
    test02();
    return 0;
}

运行结果:
在这里插入图片描述

8、类模板 派生 普通类

#include <iostream>
#include<string>
using namespace std;
//类模板
template<class T>
class Base{
private:
    T num;
public:
    Base(T num)
    {
        cout<<"有参构造"<<endl;
        this->num = num;
    }
    ~Base()
    {
        cout<<"析构函数"<<endl;
    }
    void showNum(void)
    {
        cout<<num<<endl;
    }
};

//类模板 派生 普通类 必须给基类 指定T类型
class Son1:public Base<int>{
public:
    Son1(int a):Base<int>(a)
    {
        cout<<"Son1的构造函数"<<endl;
    }
};

class Son2:public Base<string>
{
public:
    Son2(string a):Base<string>(a)
    {
        cout<<"Son2的构造函数"<<endl;
    }
};

int main(int argc, char *argv[])
{
    Son1 ob1(100);
    ob1.showNum();

    Son2 ob2("德玛西亚");
    ob2.showNum();
    return 0;
}

运行结果:
在这里插入图片描述

发布了52 篇原创文章 · 获赞 42 · 访问量 4923

猜你喜欢

转载自blog.csdn.net/weixin_43288201/article/details/105128361