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++实验三


一、模板函数(compare)

所谓函数模板,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。

在函数模板中,数据的值和类型都被参数化了,发生函数调用时编译器会根据传入的实参来推演形参的值和类型。换个角度说,函数模板除了支持值的参数化,还支持类型的参数化。

一但定义了函数模板,就可以将类型参数用于函数定义和函数声明了。说得直白一点,原来使用 int、float、char 等内置类型的地方,都可以用类型参数来代替。

1.一般模板函数

添加以下代码到queue.h

//函数模板
template<class Type>
int compare(const Type& v1, const Type& v2)
{
   if(v1<v2) return -1;
   if(v1>v2) return 1;
   return 0;
}

添加以下代码到queue.cpp

void testTemplate()
{
    double a = 1.2;
    double b = 1.5;
    cout<<"a=1.2,b=1.5,a<b:"<<compare(a,b)<<endl;       //-1

    double a1=3.0;
    double b1=2.0;
    cout<<"a1=3.0,b1=2.0,a1>b1:"<<compare(a1,b1)<<endl;         //1
}

int main(){
    testTemplate();
    return 0;
}

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

2.特化模板函数

有时通用的函数模板不能解决个别类型的问题,我们必须对此进行定制,这就是函数模板的特化。
添加以下代码到queue.h

//函数的特化
template<>
int compare<const char*>(const char * const &v1, const char * const &v2);

添加以下代码到queue.cpp

// 函数的特化
template<>
int compare<const char*>(const char * const &v1, const char * const &v2)
{
    return strcmp(v1,v2);
}
void testTemplate()
{
 //函数的特化
  	char str[10];
    char str1[10];
    strcpy(str,"abc");
    strcpy(str1,"def");
    cout<<"compare abc,def: "<<compare<const char*>(str,str1)<<endl;
    cout<<"compare def,abc "<<compare<const char*>(str1,str)<<endl;

}

int main(){
    testTemplate();
    return 0;
}

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

二、模板类Queue或Stack

C++ 中类模板的写法如下:

template <类型参数表>
class 类模板名{
成员函数和成员变量
};

类型参数表的写法如下:

class类塑参数1, class类型参数2, ...

1.模板类(Queue,Stack)

添加以下代码到queue.h

//类模板
template<class Type> class Queue;
template<class Type>
class QueueItem
{
    QueueItem(const Type &t):item(t), next(0){}
    Type item;
    QueueItem * next;
    friend class Queue<Type>;
    //加friend成全局函数
    friend ostream& operator<<(ostream& os, const Queue<Type> &q);         //输出运算符重载
public:
    QueueItem<Type>* operator++(){
        return next;
    }
    Type & operator*(){
        return item;
    }
};

//类模板
template<class Type>
class Queue
{
public:
    Queue():head(0),tail(0){}
    Queue(const Queue& q):head(0),tail(0){      //头和尾赋值为空
        copy_items(q);
    }
    //成员模板函数
    template<class It>
    Queue(It beg, It end):head(0),tail(0){copy_items(beg,end);}
    template<class It>
    void assign(It beg, It end);
    Queue& operator=(const Queue&);
    ~Queue(){destroy();}
    Type& front() {return head->item;}          //要判断是否为空
    const Type& front() const{return head->item;}
    void push(const Type &);
    void pop();
    bool empty() const{return head==0;}

    friend ostream& operator<<(ostream& os, const Queue<Type> &q){
//        os<<"< ";
        QueueItem<Type> * p;
        for(p=q.head;p;p=p->next){
            os<<p->item<<" ";
        }
//        os<<">";
        return os;
    }
    const QueueItem<Type>* Head() const{return head;}
    const QueueItem<Type>* End() const{return (tail==NULL)?NULL:tail->next;}
private:
    QueueItem<Type> * head;
    QueueItem<Type> * tail;
    void destroy();          //删除
    void copy_items(const Queue &);
    template<class It> void copy_items(It beg,It end);
};

2.成员模板函数

类模板中的成员函数放到类模板定义外面写时的语法如下:

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

用类模板定义对象的写法如下:

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

如果类模板有无参构造函数,那么也可以使用如下写法:

类模板名 <真实类型参数表> 对象名;

添加以下代码到queue.h

template<class Type>
void Queue<Type>::destroy()
{
    while (!empty()) {
        pop();
    }
}

template<class Type>
void Queue<Type>::pop(){
    if(head==0) return;
    QueueItem<Type> * p = head;
    head = head->next;
    delete p;
}
template<class Type>
void Queue<Type>::push(const Type& val){
    QueueItem<Type> * pt = new QueueItem<Type>(val);
    if(empty()){
        head = tail = pt;
    }else{
        tail->next = pt;
        tail = pt;
    }
}
template<>
void Queue<const char*>::push(const char * const &val);
template<>
void Queue<const char*>::pop();


template<class Type>
void Queue<Type>::copy_items(const Queue &orig){
    for(QueueItem<Type> *pt = orig.head;pt;pt=pt->next){
        push(pt->item);
    }
}
template<class Type>
Queue<Type>& Queue<Type>::operator=(const Queue& q)
{
    destroy();
    copy_items(q);
}

template<class Type> template<class It> void Queue<Type>::assign(It beg, It end)
{
    destroy();
    copy_items(beg,end);
//    for(It it=beg;it!=end;it++)  //或者
//    {
//        push(*it);
//    }
}

template<class Type> template<class It> void Queue<Type>::copy_items(It beg,It end)     //beg输入的data的首地址data end是data的尾地址data+5
{
    while(beg!=end){
        push(*beg);
        ++beg;
    }
}

3.模板特化:模板函数特化、模板成员函数特化、模板类特化

C++中的模板特化不同于模板的实例化,模板参数在某种特定类型下的具体实现称为模板的特化。模板特化有时也称之为模板的具体化,分别有函数模板特化和类模板特化。
模板成员函数特化:
添加以下代码到queue.h

template<class Type>
void Queue<Type>::pop(){
    if(head==0) return;
    QueueItem<Type> * p = head;
    head = head->next;
    delete p;
}
template<class Type>
void Queue<Type>::push(const Type& val){
    QueueItem<Type> * pt = new QueueItem<Type>(val);
    if(empty()){
        head = tail = pt;
    }else{
        tail->next = pt;
        tail = pt;
    }
}

template<>
void Queue<const char*>::push(const char * const &val);
template<>
void Queue<const char*>::pop();

模板类特化:
添加以下代码到queue.cpp

//类部分模板特化
template<>
void Queue<const char*>::push(const char * const &val){
    char* new_item = new char[strlen(val)+1];           //加个结束符号 存得是new_item的地址
    strncpy(new_item,val,strlen(val)+1);
    QueueItem<const char*> * pt = new QueueItem<const char*>(new_item);
    if(empty()){
        head=tail=pt;
    }else{
        tail->next = pt;
        tail = pt;
    }
}
template<>
void Queue<const char*>::pop(){
    QueueItem<const char*> * p = head;
    delete head->item;
    head = head->next;
//    delete []p->item;  //删除的是new_item
    delete p;
}

实现
添加以下代码到queue.cpp

void testTemplate()
{
    Queue<int> qt;                  //class queue的使用
    double d = 3.3;
    qt.push(1);                     //1
    qt.push(d);                     //3  int定义为整形
    qt.push(10);                    //10
    cout<<qt<<endl;

    short data[5] = {0,3,6,9};
    Queue<int> qi(data,data+5);
    cout<<qi<<endl;                 //0,3,6,9,0
    while(!qi.empty())
    {
       cout<<qi.front()<<" ";           //0,3,6,9,0
        qi.pop();
    }

    vector<int> vi(data,data+5);            //0,3,6,9,0
    qi.assign(vi.begin(),vi.end());
    cout<<endl;
    cout<<qi;

    Queue<const char*> qst;
    char str[10];
    strcpy(str,"I am");     //string copy的缩写
    qst.push(str);
    strcpy(str,"03");
    qst.push(str);
    strcpy(str,"huang");
    qst.push(str);
    cout<<endl<<qst<<endl;

}

int main(){
    testTemplate();
    return 0;
}

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

三、模板类AutoPtr

智能指针的一种通用实现技术是使用引用计数。智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象。智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。

1.构造函数

添加以下代码到autoptr.h

template<class T>
class AutoPtr
{
public:
    AutoPtr(T* pData);//构造函数
};

template<class T>
AutoPtr<T>::AutoPtr(T* pData)
{
    m_pData = pData;        //new一个存用户数的地方
    m_nUser = new int(1);       //new一个初始化的int
}

2.析构函数

添加以下代码到autoptr.h

template<class T>
class AutoPtr
{
public:
    AutoPtr(T* pData);//构造函数
    ~AutoPtr();//生命周期结束 析构函数
};

template<class T>
AutoPtr<T>::~AutoPtr(){
    decrUser();         //用户减一
}

template<class T>
void AutoPtr<T>::decrUser()
{
    --(*m_nUser);
    if((*m_nUser)==0){      //地址为空
        delete m_pData;
        m_pData = 0;
        delete m_nUser;
        m_nUser = 0;
    }
}

3.拷贝构造函数

添加以下代码到autoptr.h

template<class T>
class AutoPtr
{
public:
    AutoPtr(T* pData);//构造函数
    AutoPtr(const AutoPtr<T>& h);			//拷贝构造函数
    AutoPtr<T>& operator=(const AutoPtr<T>& h);//拷贝构造函数
    ~AutoPtr();//生命周期结束 析构函数
};

//拷贝构造函数
template<class T>
AutoPtr<T>::AutoPtr(const AutoPtr<T>& h)
{
    m_pData = h.m_pData;
    m_nUser = h.m_nUser;
    (*m_nUser)++;
}
//拷贝构造函数
template<class T>
AutoPtr<T>& AutoPtr<T>::operator=(const AutoPtr<T>& h)
{
    if(this==&h) return *this;
    decrUser();
    m_pData = h.m_pData;
    m_nUser = h.m_nUser;
    (*m_nUser)++;
    return *this;
}

4.等号、->、*等运算符重载

添加以下代码到autoptr.h

template<class T>
class AutoPtr
{
public:
    AutoPtr(T* pData);//构造函数
    AutoPtr(const AutoPtr<T>& h);
    AutoPtr<T>& operator=(const AutoPtr<T>& h);
    ~AutoPtr();//生命周期结束 析构函数
    T* operator->(){        //指针运算符重载
        return m_pData;
    }
    T& operator*(){
        return *m_pData;
    }
    const T& operator *() const{
        return *m_pData;
    }
    const T* operator ->() const{       //返回的指针不能被改变
        return m_pData;
    }

private:
    void decrUser();
     T * m_pData;
    int * m_nUser;
};

5.主函数调用AutoPtr

添加以下代码到main.cpp。
CMatrix.h ,CMatrix.cpp自行添加到文件夹中

#include "autoptr.h"
#include "cmatrix.h"
void TestAutoPtr()
{
    AutoPtr<CMatrix>h1(new CMatrix);
    double data[6] = {1,2,3,4,5,6};
    h1->Create(2,3,data);
    cout<<*h1<<endl;

    AutoPtr<CMatrix> h2(h1);
    (*h2).Set(0,1,10);          //h2进行修改 0行第1列改成10
    cout<<*h1<<endl<<*h2<<endl;             //1 10 3 4 5 6  h2跟h1指向了同一个地方
}


int main(){
//    testTemplate();
    TestAutoPtr();
    return 0;
}

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

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 17:31:50  更:2021-12-01 17:32:45 
 
开发: 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年11日历 -2024/11/24 8:38:23-

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