栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 模板类与智能指针

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 模板类与智能指针

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录
  • 前言
  • 一、pandas是什么?
  • 二、使用步骤
    • 1.引入库
    • 2.读入数据
  • 总结



前言

本次实验将实现模板类,模板函数,模板函数特化,智能指针的设计,并对其进行相应测试。



一、实验内容

一、模板函数(compare)
        1.一般模板函数
        2.特化模板函数
二、类模板Queue
        1.类模板(Queue)
        2.成员模板函数
        3.模板特化:模板函数特化、模板成员函数特化、模板类特化
三、模板类AutoPtr
        1.构造函数
        2.析构函数
        3.拷贝构造函数
        4.等号、->、*等运算符重载
        5.6主函数调用AutoPtr


二、实验过程
1.模板函数
int compare(int a,int b)
{
    return a>b? a:b;
}
double compare(double a,double b)
{
    return a>b? a:b;
}

这两个函数都是用来判断a和b的大小,只有参数类型不同,功能完全一样,类似这种的情况,如果能写一段通用代码适用于多种不同数据类型,便会使代码的可重用性大大提高,从而提高软件的开发效率。使用模板函数就是为了这一目的。只需对模板函数编写一次,然后基于调用函数时提供的参数类型,C++编译器将自动产生相应的函数来正确的处理该类型的数据。

函数模板的定义形式:

template<模板参数表>

类型名  函数名(参数表)

{
        函数体的定义
}

1.1 一般模板函数
template         //class关键字表明T是一个类型,在模板定义中class和typename作用相同
int compare(const T &a,const T &b)
{                         //使用模板函数,函数的传入参数类型必须相同,即不能一个int,一个double
    if(a>b)
        return 1;
    else if(a>a>>b;
    cout<<"result is:";
    cout< 

注:1.函数模板本身在编译时不会生成任何目标代码,只有由模板生成的实例会生成目标代码;

        2.被多个源文件引用的函数模板,应当连同函数体一同放在头文件中,而不能像普通函数一样只将声明放在头文件中;

        3.函数指针也只能指向模板的实例,而不能指向模板本身。

运行结果:

 1.1 特化模板函数
template<>
int compare(const char * const &v1, const char * const &v2)
{
    return strcmp(v1,v2);   //比较两个字符串
    //根据比较结果返回一个int类型的值。如果返回值小于0,则表示在ASCII码表上v1字符串小于v2字符串
}
void testCompare()
{
    const char *v1 = "hello";  //或const char * const v1 = "hello";
    //与指针指向的数据类型是const有关还是非const有关,而与指针是const还是非const无关
    const char *v2 = "world";
    cout< 

注:1.compare后指定特化时的模板形参即const char *类型,就是说在以实参类型const char * 调用函数时,将产生该模板的特化版本。

        2.形参“const char * const &v1”去掉修饰符const,实际类型是char * &v1,也就是v1是一个引用,一个指向char型指针的引用,即指针的引用,加上const,v1 就是一个指向const char 型指针的const引用;所以不能用一个指向非const 数据的指针调用特化版本,因为数据类型不匹配。

        3.由于compare声明的形参都是const char *,即char *型指针存储的是const 数据,所以不能传递一个存储了非const数据的char *型指针。同时由于编译器对特化版本不进行实参形参的常规转换,所以调用的实参必须与特化版本的声明完全一致,否则将从泛型(一般型)版本进行实例化,或者函数匹配错误。

        4.被特化的函数模板,无论是否被调用,相关的目标代码都会生成,因此他们的定义放在源文件(.cpp)中,而非头文件中。

运行结果:

2.类模板(Queue) 2.1 类模板

使用模板类可以使用户为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、返回值或局部变量能取不同类型(包括系统预定义和用户自定义的)。

类模板声明的语法形式:

template <模板参数表>
class 类名
{
        类成员声明
{

定义一个类模板Queue和管理类QueueItem,实现向队列中增加元素,删除元素等操作。

template      //Type表示通用数据类型,即可以取任意返回值
class Queue;              
template      //类模板的定义,类模板的使用实际上是将类模板实例化成一个具体的类
class QueueItem
{
    Type item;
    QueueItem * next;
    QueueItem(const Type& val):item(val),next(NULL){}   //参数列表构造器方法
    friend Queue;      //将队列定义为友元类,方便访问私有变量
    friend ostream& operator<<(ostream &os,const Queue &que);
public:
    QueueItem* operator++()
    {
        return next;     //返回队列下一个元素的指针
    }
    Type & operator*()  //取出存储的元素
    {
        return item;
    }
};

template
class Queue
{
public:
    Queue();
    Queue(const Queue &q);
    ~Queue();
    bool isEmpty();                        //判断队列是否为空
    void Push(const Type& val);          //在队列里面增加元素
    void Pop();                          //在队列里面删除元素
    void destroy();                      //清空队列
    Type& front();                       //输出队列中的第一个元素
    void copy_item(const Queue &orig);   //拷贝全部队列
    template                   //成员模板函数
    Queue(It beg,It end);                //新的有参构造函数
    template
    void assign(It beg,It end);          //向队列中添加指定数据
    template
    void copy_items(It beg,It end);      //拷贝部分队列
    //访问头部和尾部的函数
    const QueueItem* Head() const{return head;}
    const QueueItem* End() const{return(tail==NULL)? NULL:tail;}

private:
    QueueItem * head;    //队列头指针
    QueueItem * tail;    //队列尾指针,使用含有模板类组成的QueueItem类需要使用模板声明
    friend ostream& operator<<(ostream &os,const Queue &que)
    {
        os<<"< ";
        for(QueueItem * p = que.head;p!=NULL;p=p->next)
        {

            os<item<<"  ";
        }
        os<<">";
        return os;
    }
};

一个类模板声明自身并不是一个类,只有当被其他代码引用时,模板才根据引用的需要生成具体的类,即类模板的使用-----实例化成一个具体的类

2.2 成员模板函数的实现

定义的语法格式:

template <模板参数表>
类型名 类名<模板参数标识符列表>::函数名(参数表)

成员模板函数同样要写在.h文件里

template 
Queue::Queue():head(NULL),tail(NULL)     //指针必须初始化
{

}
template 
Queue::Queue(const Queue &q):head(NULL),tail(NULL)
{
    copy_items(q);     //拷贝构造器
}
template 
Queue::~Queue()
{
    destroy();
    cout<<"delete Queue"<
void Queue::copy_item(const Queue &orig)     //拷贝全部队列
{
    for(QueueItem *pt = orig.head;pt!=NULL;pt=pt->next)
    {
        push(pt->item);
    }
    //将队列orig的所有元素插入其他队列,原队列仍然保留
}
template 
bool Queue::isEmpty()
{
    if(head==NULL)
        return true;
    else
        return false;
}
template 
void Queue::Push(const Type& val)
{
    QueueItem * pt = new QueueItem(val);
    if(isEmpty())
    {
        head = tail = pt;
    }
    else
    {
        tail->next = pt;
        tail = pt;
    }
}
template
void Queue::Pop()
{
    QueueItem * p = head;
    head = head->next;
    delete p;    //释放空间
}
template
Type& Queue::front()
{
    Type ans = 0;
    if(!isEmpty())
    {
        return head->item;
    }
    else
    {
        cout<<" Queue is NULL!"<
void Queue::destroy()
{
    while (!isEmpty())
    {
        Pop();
    }
    head = tail =NULL;
}
template
template
Queue::Queue(It beg,It end):head(NULL),tail(NULL)
{
    copy_items(beg,end);
}
template
template
void Queue::assign(It beg,It end)
{
    destroy();
    copy_items(beg,end);

}
template
template
void Queue::copy_items(It beg,It end)
{
    for(It it=beg;it!=end;it++)
    {
        Push(*it);
    }
}

对编写的类模板和其成员函数进行测试:

void testQueue()
{
    //Queue qt;       //为什么用int输出是10,4,20;double输出是10,4.4,20
    //因为定义的对象的真实数据类型是int,所以会进行强制类型转换,输出的是4
    //类模板定义对象:类模板名<真实数据类型> 对象名;
    Queue qt;
    double c=4.4;
    qt.Push(10);
    qt.Push(c);
    qt.Push(20);
    cout< qt1(data,data+5);
    cout< vi(data,data+5);               //数组
    qt1.assign(vi.begin()+1,vi.end()-1);       //列表中添加3,6,9
    cout< 

运行结果:

 2.3 模板函数特化

当我们所写的模板无法适应所有数据类型时,就需要对部分函数进行特化,为了能输出想要的字符串结果,对字符串数据进行特化

//争对const char*数据类型对Push()函数进行特化
template<>
void Queue::Push(const char * const &val)
{
    char* new_item = new char[strlen(val)+1];   //根据字符串长度进行创建字符数组
    strncpy(new_item,val,strlen(val)+1);        //拷贝字符串内容
    QueueItem * pt = new QueueItem(new_item);
    if(isEmpty())
    {
        head=tail=pt;
    }
    else{
        tail->next = pt;
        tail = pt;
    }
}
对Pop()函数进行特化
template<>
void Queue::Pop()
{
    QueueItem * p = head;  //特化模板类QueueItem
    delete head->item;          //释放char *数据
    head = head->next;
    delete p;                   //释放指针空间
}
 2.4 模板类的特化

针对const char*数据类型对类模板Queue实现特化

template<>
class Queue    //针对const char*数据类型对Queue实现特化
{
public:    
    void Push(const char* const &val)
    {
        //real_que.Push(val);    //会先进行类型转换,将const char*转成string类型 //第一种特化
        
        char* new_item = new char[strlen(val)+1];   //根据字符串长度进行创建字符数组
        strncpy(new_item,val,strlen(val)+1);        //拷贝字符串内容
        QueueItem * pt = new QueueItem(new_item);
        if(isEmpty())
        {
            head=tail=pt;
        }
        else{
            tail->next = pt;
            tail = pt;
        } 
    }
    void Pop()
    {
        //real_que.Pop();
        
        QueueItem * p = head;  //特化模板类QueueItem
        delete head->item;          //释放char *数据
        head = head->next;
        delete p;                   //释放指针空间   
    }
    void destroy()
    {
        while (!isEmpty())
        {
            Pop();
        }
        head = tail =NULL;
    }
    bool isEmpty() const
    {
        if(head==NULL)
            return true;
        else
            return false;
    }
    string & front()
    {
        return real_que.front();
    }
    void copy_item(const Queue &orig);  
    friend ostream & operator<<(ostream& os,Queue &que)
    {
        os< real_que;
    QueueItem *head;
    QueueItem *tail;
};

测试特化类和特化函数:

void testQueue1()
{
    Queue qst;
    qst.Push("I am");
    qst.Push("Ren");
    qst.Push("Ruijie");
    cout< 

运行结果:

3.智能指针 3.1 智能指针的创建

智能指针的作用是管理一个指针,因为存在以下这种情况:申请的空间在函数结束时忘记释放,造成内存泄漏。使用智能指针可以很大程度上的避免这个问题,因为智能指针是一个类,当超出了类的实例对象的作用域时,会自动调用对象的析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。

对一个对象进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过构造函数传入普通指针。

3.2 测试智能指针



总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/511949.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号