IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++-模板 -> 正文阅读

[C++知识库]c++-模板

函数模板

相当于函数重载的进阶,类型参数化

数据的类型也可以通过参数传递
在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器根据传入的实参自行推断数据类型,相当于类型参数化

函数模板

建立一个通用函数,用到的数据类型(返回值、形参类型、局部变量类型)无需具体指定,用一个标识符来站位,等发生函数调用时再根据传入的实参来逆推出真正的类型
一旦定义类函数模板,就可以将类型参数 用于函数定义和函数声明,(将内置类型的地方,用类型参数来代替)

template函数模板关键字 <>占位符 typename T声明具体的类型参数,类型参数是T
template <typename T>模板头,模板头中包含的类型参数可以用在函数定义的各个位置,包括返回值、形参列表和函数体

#include <iostream>
using namespace std;

template <typename T> T mmax(T a,T b);

template <typename T> void swap(T *a,T *b) // template<class T> void swap(T *a,T *b) 也是可以的
{
    T temp=*a;
    *a=*b;
    *b=temp;
}

template <typename T> // 可换行,但不能有分号
T mmax(T a,T b)
{
    if (a>=b)
        return a;
    else
        return b;
}

int main()
{
    int a=10,b=20;
    swap(&a,&b);
    cout<<a<<" "<<b<<endl;

    char c='a',d='b';
    swap(&c,&d);
    cout<<c<<" "<<d<<endl;

    bool e=false,f=true;
    swap(&e,&f);
    cout<<e<<" "<<f<<endl;

    cout<<mmax(a,b)<<endl;

    return 0;
}

类模板

类模板中定义的类型参数可以在类声明和类定义中

template<typename T1,typename T2> 
class MyPoint
{
private:
    T1 x;
    T2 y;
public:
    MyPoint(T1 x,T2 y);
    void setx(T1 x);
    T1 getx() const;
    void sety(T2 y);
    T2 gety() const; // const 成员函数 不能修改成员this的成员值

    MyPoint *print() const;
};

template<typename T1,typename T2>
MyPoint<T1,T2>::MyPoint(T1 x,T2 y)
{
    this->x=x;
    this->y=y;
}

template<typename T1,typename T2> 
void MyPoint<T1,T2>::setx(T1 x)
{
    this->x=x;
}

template<typename T1,typename T2> 
void MyPoint<T1,T2>::sety(T2 y)
{
    this->y=y;
}

template<typename T1,typename T2> 
T1 MyPoint<T1,T2>::getx() const
{
    return this->x;
}

template<typename T1,typename T2> 
T2 MyPoint<T1,T2>::gety() const
{
    return this->y;
}

template<typename T1,typename T2> 
MyPoint<T1,T2>* MyPoint<T1,T2>::print() const
{
    return new MyPoint(this->x,this->y);
}

int main()
{
    // 创建对象
    MyPoint<int,int> p1(1,2);
    MyPoint<float,float> p2(3.,4.);
    MyPoint<int,char*> p3(5,"lisi");

    // 创建对象
    MyPoint<int,int> *p4=new MyPoint<int,int>(6,7);

    // 接收返回值
    MyPoint<int,int> *point_ptr=p1.print();
    cout<<point_ptr->getx()<<" "<<point_ptr->gety()<<endl;

    // 接收返回值
    MyPoint<float,float> *point_ptr2=p2.print();
    cout<<point_ptr2->getx()<<" "<<point_ptr2->gety()<<endl;

    delete point_ptr;
    delete point_ptr2;
    delete p4;

    return 0;
}

例子2 !!!

#include <iostream>
using namespace std;

template <typename T>
class List
{
private:
    int length; // 数组个数
    T *ptr; //数组指针
public:
    List(int length);
    List(List &arr); // 构造函数重载
    ~List();

    void push_back(const T &v); // 添加元素
    // List & operator=(const List &a); // 数组见赋值, 成员函数,返回的是引用

    T size();
    T & operator[](int idx); // 成员函数,返回的是引用
};

template <typename T>
List<T>::List(int length)
{
    this->length=length;
    if (length==0)
    {
        this->ptr=NULL;
    }
    else
    {
        this->ptr=new T[this->length]();
    }
}

template <typename T>
List<T>::List(List &arr)
{
    if (!arr.ptr)
    {
        this->ptr==NULL;
        this->length=0;
        return ; // 这个也很重要
    }

    this->ptr=new T[arr.length];
    memcpy(this->ptr,arr.ptr,sizeof(T)*arr.length); // 内存赋值
    this->length=arr.size;
}

template <typename T>
List<T>::~List()
{
    if (this->ptr)
    {
        delete[] this->ptr;
    }
    cout<<"析构"<<endl;
}

template <typename T>
void List<T>::push_back(const T &v)
{
    if (this->ptr)
    {
        // 注意写法!!!
        T *temp_ptr=new T[this->length+1](); // 重新分配空间
        memcpy(temp_ptr,this->ptr,sizeof(T)*this->length); // 拷贝原有数组;
        delete[] this->ptr;
        this->ptr=temp_ptr;
    }
    else
    {
        this->ptr=new T[1]();
    }
    this->ptr[this->length++]=v;
}

template <typename T>
T List<T>::size()
{
    return this->length;
}

template <typename T>
T & List<T>::operator[](int idx)
{
    return this->ptr[idx];
}


int main()
{
    List<int> L(3);
    cout<<L.size()<<endl; // 3

    L.push_back(10);
    L.push_back(20);
    L.push_back(30);
    cout<<L.size()<<endl; // 6

    // 如果不重载[]的话,ptr和length是私有方法不能被访问
    cout<<L[3]<<endl;

    return 0;
}

模板重载

#include <iostream>
using namespace std;

template <typename T> void mswap(T &a,T &b);
template <typename T> void mswap(T a[],T b[],int len);
template <typename T> void printArray(T arr[],int len);

int main()
{
    int a=10,b=20;
    cout<<a<<" "<<b<<endl;
    mswap(a,b);

    int arr1[3]={1,2,3};
    int arr2[3]={4,5,6};
    
    cout<<"******"<<endl;
    printArray(arr1,3);
    cout<<"******"<<endl;
    printArray(arr2,3);
    
    mswap(arr1,arr2,3);
    
    cout<<"******"<<endl;
    printArray(arr1,3);
    cout<<"******"<<endl;
    printArray(arr2,3);

    return 0;
}

template <typename T> void mswap(T &a,T &b)
{
    T temp=a;
    a=b;
    b=temp;
}

template <typename T> void mswap(T a[],T b[],int len)
{
    T temp;
    for (int i=0;i<len;i++)
    {
        temp=a[i];
        a[i]=b[i];
        b[i]=temp;
    }
}

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

参数类型推断

类型转换

template <typename T> void func(T a, T b);
func(1,2.3); // 错误不能进行隐式的类型转换,且不知道T应该是哪个类型

template <typename T> void func(T a);
int a[10];
func(a); // T的类型为int *, 会进行类型转换

template <typename T> void func(T &a);
int a[10];
func(a); // 当函数参数是引用类型时,数组不会转换为指针,T的类型为int [10]

注意

当显示指明类型参数时,可以进行类型转换(隐式)

template <typename T> void func(T a, T b);
func<float>(1,2.3); // 正确的

显示指明

// 函数调用过程中只能推断出T1 不能推断出 T2,所以必须显示指明
template <typename T1,typename T2> func(T1 a)
{
    T2 b;
}

// 显示指明是,是按顺序指明的
func<int,int>(10) 

模板进阶 – 还没看

7.6

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-12-25 10:47:31  更:2022-12-25 10:50:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/23 16:14:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码