C++模板

目录

1、函数模板:

(1)、普通函数和函数模板的区别:

(2)、普通函数和函数模板同名:

(3)、函数模板的局限性:

(4)、设计一个算法来打印任意数据类型的数组和数组排序

2、类模板:

(1)、类模板概述

(2)、类模板的份文件实现

(3)、类模板作为函数参数

(4)、类模板的派生

1)、类模板派生出普通类

2)、类模板派生出类模板

3、模板类的应用:


1、函数模板:

函数模板关键字:template

定义:可以把形参的类型抽象化,用虚拟类型T表示,这叫做函数模板,根据实参确定来推到T的类型。

#include 

using namespace std;
template 
//typename明确T是类型
void test01(T1 &a,T2 &b)
{
    T1 temp = a;
    a = b;
    b = temp;
}
void test02()
{
    int a = 10;
    int b = 20;
    test01(a,b);
    cout<

运行结果:

C++模板_第1张图片

函数模板的意义:为了实现泛型编程,减轻编程的工作量,增强函数的重用性。

函数模板的特性:

1、函数模板本身的编译。

2、调用位置自动推导T的类型,再将函数编译成函数模板(类型替换)。

注意:函数模板在调用时会自动推导T的类型,不会自动类型转换。

swapAllType(10, 'a'); //错误

(1)、普通函数和函数模板的区别:

1、函数模板不允许自动类型转换,在识别变量的类型之后不能改变。

2、普通函数可以进行自动类型转换(形参已经固定的情况下,要注意精度丢失)

(2)、普通函数和函数模板同名:

优先使用普通函数,如要用函数模板要加<>强制使用

swapALLType<>(a,b)

(3)、函数模板的局限性:

函数模板的局限性

1、编译时间长

2、难以调试,函数模板在编译的阶段生成

3、可读性差

利用打印出一个对象引出函数模板的局限性:由于cout<<不能直接打印实例化对象,所以可以重载或者采用函数模板特例化 template<>void printALLType(person ob)。

解决方法:1、函数模板参数具体化;2、重载运算符

函数模板参数具体化:

#include 
#include
using namespace std;

//函数模板,在编译阶段执行。
template 
void printALLType(T a)
{
    cout<<" T = "<< a<< endl;
}
class person
{
   friend void printALLType(person ob);
private:
    int num;
    string name;
public:
    person(int num,string name):num(num),name(name)
    {
    }
    ~person(){}
};
//函数模板的特例化,相当于实例化一个函数模板来解决问题
//如果直接调用函数模板会出现问题需要重载<<,特例化之后
//我们直接在参数中实例化一个对象

template<> void printALLType(person ob)
{
    cout<

(4)、设计一个算法来打印任意数据类型的数组和数组排序

思路:

1、函数模板来实现任意数据的打印还有排序。

2、当类数组(数组里面存放的同一个类的不同对象)排序和遍历需要函数重载

//设计一个算法可以打印任意数组类型的数组和排序
//思路函数模板

#include 
#include
using namespace std;

class data
{
    friend ostream &operator <<(ostream &cout,data &ob);
private:
    int a;
public:
    data(){}
    data(int a):a(a){}
bool operator <(data &ob)
{
    return (a
void print(T *arr,int n)
{
    for(int i =0;i < n;i++)
    {
        cout<
void sort(T *arr,int n)
{
    for(int i =0;i < n-1;i++)
    {
        for(int j =0;j < n-i-1;j++)
        {
            if(arr[j+1] < arr[j])
                //如果是类的比较需要重载<
            {
                T temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}

void test01()
{
    int arr1[5] = {30,10,50,20,40};
    sort(arr1,5);
    print(arr1,5);

    char arr2[] ="hello world";
    sort(arr2,sizeof(arr2));
    print(arr2,sizeof(arr2));
    //类定义arr3数组创建五个匿名对象,调用初始化列表
    data arr3[5] ={data(200),data(300),data(100),data(600),data(500)};
    sort(arr3,5);
    print(arr3,5);
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

运行结果:

C++模板_第2张图片

2、类模板:

(1)、类模板概述

将类中的类型抽象化,该类称为函数模板

类模板在实例化的时候必须指定类型  personob1(1,2);


#include 
#include
using namespace std;
template //类模板,根据成员变量个数决定参数
class person
{
private:
    T1 a;
    T2 b;
public:
    person(){}
    person(T1 a,T2 b):a(a),b(b)
    {

    }
    ~person(){}
    void show()
    {
        cout<ob1(1,2);
    ob1.show();

    personob2('a','b');
    ob2.show();
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

类模板实例化时,必须指定T1和T2的类型。

(2)、类模板的份文件实现

注意:构造函数或者成员函数在外部定义他的作用域变成了类名 ::

template
person::person(T1 a, T2 b)//类外定义构造函数模板类作用域是person
{
    this->a =a;
    this->b =b;
}

(3)、类模板作为函数参数

     注意:1、类模板做参数,可以接受任意类型

                2、声明友元函数需要加上  template


#include 
#include
using namespace std;
template //类模板,根据成员变量个数决定参数
class person
{
    friend void show2(person &ob);

    template //类模板作为形参.也作为友元函数。
    friend void show3(person&ob);
private:
    T1 a;
    T2 b;
public:
    person(){}
    person(T1 a,T2 b);
    ~person(){}
    void show1();

};


template
person::person(T1 a, T2 b) //类外定义作用域是person
{
    this->a =a;
    this->b =b;
}

template
void person::show1() //类外定义作用域是person
{
    cout< &ob)
//只能访问类型是int int的类模板
{
   cout<//类模板作为形参,可以访问任何类型的类模板
void show3(person&ob)
{
    cout<ob1(1,2);
    ob1.show1();

    personob2('a','b');
    ob2.show1();
}

int main(int argc, char *argv[])
{
    test01();
    return 0;
}

(4)、类模板的派生

1)、类模板派生出普通类

子类实例化的时候需要知道父类是什么类型,也就是具体化父类类型,方便编译器分配子类的内存

template //类模板,根据成员变量个数决定参数
class person
{
    
private:
    T1 a;
    T2 b;
public:
    person(){}
    person(T1 a,T2 b);
    ~person(){}

};
class boy:public person//继承的时候也得表明是类模板
{
public:
    int c;
    boy(){}
    boy(int a,int b,int c):person(a,b),c(c){}
    //子类初始化父类的时候
};

2)、类模板派生出类模板

注意:与派生出普通函数的区别就是,在声明式模板类的时候需要加上父类的模板类型

template //模板函数继承模板函数得加上父类的模板类型
class other:public person
{
public:
    T d;
    other(){}
    other(int a,int b,int d):person(a,b),d(d){}
};

3、模板类的应用:

设计一个数组模板类,完成对不同类型的元素的管理

myarray.h

#ifndef MYARRAY_H
#define MYARRAY_H

#include
using namespace std;

template 
class MyArray
{
    template
    friend ostream & operator <<(ostream &cout,MyArray &ob);
private:
    T *arr;
    int capacity;
    int size;
public:
    MyArray();
    MyArray(int capacity);
    MyArray(const MyArray &ob);
    ~MyArray();

    void pushBack(T elem);//添加元素
    void popBack();//删除元素
    int getCapacity();//得到容量的大小
};

template
ostream &operator <<(ostream &cout, MyArray &ob)
{
    for(int i =0;i < ob.size;i++)
    {
        cout<
MyArray::MyArray()
{
    size = 0;
    capacity = 5;
    arr = new T[capacity];
}

template
MyArray::MyArray(int capacity)
{
    this->capacity =capacity;
    this->size = 0;
    arr =new T[capacity];
}

template
MyArray::MyArray(const MyArray &ob)
{
    this->capacity =ob.capacity;
    this->size =ob.size;
    this->arr = new T[capacity];
    memcpy(this->arr,ob.arr,size*sizeof(T));

}

template
MyArray::~MyArray()
{
    if((this->arr) != nullptr)
    {
        delete []arr;
        arr = nullptr;
    }
}

template
void MyArray::pushBack(T elem)
{
    if(size == capacity)
    {
        T *tempArr = new T[2*capacity];
        memcpy(tempArr,arr,size*sizeof(T));
        delete []arr;
        arr =nullptr;
        arr = tempArr;
        capacity = 2*capacity;
    }
    arr[size] = elem;
    size++;
}

template
void MyArray::popBack()
{
    if(size == 0)
    {
        std::cout<<"数组为空"<
int MyArray::getCapacity()
{
    return capacity;
}


#endif // MYARRAY_H

main.cpp


#include 
#include
#include"myarray.h"

using namespace std;
class Data
{
    friend ostream & operator <<(ostream &out, Data ob);
private:
    int a;
public:
    Data(){}
    Data(int a):a(a){}
};
ostream & operator <<(ostream &out, Data ob)
{
    out << ob.a;
    return out;
}

int main(int argc, char *argv[])
{

    MyArray arr;
    arr.pushBack(30);
    arr.pushBack(10);
    arr.pushBack(40);
    arr.pushBack(20);
    arr.pushBack(50);
    arr.pushBack(70);

    cout< arr1;
    Data ob(30);
    Data ob1(40);
    Data ob2(10);
    Data ob3(20);
    Data ob4(60);
    Data ob5(50);
    arr1.pushBack(ob);
    arr1.pushBack(ob1);
    arr1.pushBack(ob2);
    arr1.pushBack(ob3);
    arr1.pushBack(ob4);
    arr1.pushBack(ob5);
    arr1.pushBack(Data(80));
    cout<

运行结果:

C++模板_第3张图片

你可能感兴趣的:(C++,c++,开发语言,算法)