C++实验(三)——模板

目录

模板的概念

函数模板

类模板

实验

一、模板函数(compare)

一般模板函数

 特化模板函数

二、模板类Queue或Stack

queue.h

扫描二维码关注公众号,回复: 13464351 查看本文章

类模板的特化

模板成员函数特化

三、模板类AutoPtr


模板的概念

模板就是建立通用的模具,大大提高复用性

C++提供两种模板机制:函数模板类模板

函数模板针对仅参数类型不同的函数;

类模板针对仅数据成员和成员函数类型不同的类。

函数模板

  • template<typename T> 函数声明或定义

  • 使用函数模板有两种方式:自动类型推导、显示指定类型

类模板

  • 建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表。
  • template<typename T> 类

类模板与函数模板区别主要有两点:

  1. 类模板没有自动类型推导的使用方式
  2. 类模板在模板参数列表中可以有默认参数

实验

一、模板函数(compare)

一般模板函数

#include "mainwindow.h"
#include<iostream>
#include <QApplication>

template <class Type>
int compare(const Type &v1,const Type &v2)
{
    if(v1<v2)
        return -1;
    if(v1>v2)
        return 1;
    return 0;
}
int main(int argc, char *argv[])
{
    const char *cp1="world",*cp2="hi";
    int a=1,b=2;
    compare(a,b);
    compare(cp1,cp2);
    return 0;
    /*
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();*/
}

运行结果

 特化模板函数

当函数模板需要对某些类型进行特化处理,称为函数模板的特化。

template<>
int compare<const char*>(const char * const &v1, const char * const &v2)
{
    cout<<"specialization"<<endl;
    return strcmp(v1,v2);
}

运行结果

同时,函数模版的特化,当函数调用发现有特化后的匹配函数时,会优先调用特化的函数,而不再通过函数模版来进行实例化。

二、模板类Queue或Stack

类模板example

#include <string>
#include<iostream>
using namespace std;
//类模板
template<class T1, class T2 = int>
class Person
{
public:
    Person(T1 name, T2 age)
    {
        this->mName = name;
        this->mAge = age;
    }
    void showPerson()
    {
        cout << "name: " << this->mName << " age: " << this->mAge << endl;
    }
public:
    T1 mName;
    T2 mAge;
};

//1、类模板没有自动类型推导的使用方式
void test1()
{
    Person <string ,int>p("xxd", 1000); //必须使用显示指定类型的方式,使用类模板
    p.showPerson();
}

//2、类模板在模板参数列表中可以有默认参数
void test2()
{
    Person <string> p("jmu", 999); //类模板中的模板参数列表 可以指定默认参数
    p.showPerson();
}

int main() {
    test1();
    test2();
    return 0;
}

类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板

运行结果

queue

  • push():会将一个元素置入queue中;
  • front():会返回queue内的第一个元素
  • back():会返回queue中的最后一个元素
  • pop():会移除queue内的第一个元素
     

queue.h

#ifndef QUEUE_H
#define QUEUE_H

#include <iostream>

using namespace std;


template<class Type> class Queue; //先声明 Queue

template<class Type>
class QueueItem{
    QueueItem(const Type &t):item(t),next(0){}
    Type item;
    QueueItem *next;
    friend class Queue<Type>;//友元函数 访问
    friend ostream& operator<<(ostream& os,const Queue<Type> &q); //运算符重载

    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(),tail(){
        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(){destory();}

    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 destory();
        void copy_items(const Queue &);
        template<class It> void copy_items(It beg,It end);

};

//成员模板函数
template<class Type>
void Queue<Type>::destory(){
        while(!empty()){
            pop();
        }
}

//移除第一个元素
template<class Type>
void Queue<Type>::pop(){
    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)
{
    destory();
    copy_items(q);
}

template<class Type> template<class It> void Queue<Type>::assign(It beg, It end)
{
    destory();
    copy_items(beg,end);
}

template<class Type> template<class It> void Queue<Type>::copy_items(It beg,It end)
{
    while(beg!=end){
        push(*beg);
         ++beg;
    }
 }

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

template<>
int compare<const char*>(const char * const &v1, const char * const &v2);


#endif // QUEUE_H

类模板的特化

当类模板内需要对某些类型进行特别处理时,使用类模板的特化。

模板成员函数特化

实现模板类Queue中的成员函数push()pop()方法的特化版本,使其能够实现字符串的入队和出队操作。

#include "Queue.h"
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
template <>
void Queue<const char*>::push( const char * const & str)
{
    char * pVal = new char[strlen(str)+1];
    strcpy(pVal,str);
    QueueItem<const char*> * p = new QueueItem<const char*>(pVal);
    if(empty())
    {
        head = tail = p;
    }
    else {
        tail->next = p;
        tail = p;
    }
}

template<>
void Queue<const char* >::pop()
{
    if(empty())
    {
        return;
    }
    QueueItem<const char*> * p = head;
    head = head->next;
    delete []p->item;
    delete p;
}


运行结果

三、模板类AutoPtr

智能指针

C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。程序员自己管理堆内存可以提高了程序的效率,但是整体来说堆内存的管理是麻烦的,所以引入了智能指针的概念,方便管理堆内存。使用普通指针,容易造成堆内存泄露(忘记释放),二次释放,程序发生异常时内存泄露等问题等,使用智能指针能更好的管理堆内存。

测试

#include <iostream>
#include <memory>
 
using namespace std;
 
class Test
{
public:
    Test(int param = 0)                    //调用时,可以指定是第几个对象。默认第0个
    {
        num = param;
        cout << "Simple:" << num << endl;
    }
    
    ~Test()                                //析构时会指出第几个对象被析构。
    {
        cout << "~Simple:" << num << endl;
    }
 
    void PrintSomething()                  //输出附加的字符串方法。
    {
        cout << "PrintSomething:" << info_extend.c_str() << endl;
    }
 
    int num;                               //代表这个对象的序号。
    string info_extend;                    //附加的字符串。
 
};


void TestAutoPtr1()
{
    auto_ptr<Test> my_auto (new Test(1));    //绑定一个Test类的新建对象
    if(my_auto.get())                        //get函数用来显式返回它拥有的对象指针,此处判非空
    {
        my_auto->PrintSomething();
        my_auto.get()->info_extend = "Addition"; //对类内成员进行操作
        my_auto->PrintSomething();              //看是否成功操作
        (*my_auto).info_extend += " other";     //实验解引用操作
        mt_auto->PrintSomething();
    }
}

测试结果

最后函数结束后,在调用析构函数的同时auto_ptr的析构函数也将Test类的对象delete掉

#ifndef AUTOPTR_H
#define AUTOPTR_H
template <class T>
class AutoPtr
{
public:

    AutoPtr(T* pData);
    AutoPtr(const AutoPtr<T>& h);
    //调用析构函数
    ~AutoPtr();
    AutoPtr<T>& operator=(const AutoPtr<T>& h);
    void decrUser();

    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:
    T* m_pData;
    int* m_nUser;
};
template < class T>
AutoPtr<T>::AutoPtr(T* pData)
{
    m_pData = pData;
    //初始化用户数为1
    m_nUser = new int(1);
}
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)
{
    decrUser();
    m_pData = h.m_pData;
    m_nUser = h.m_nUser;
    (*m_nUser)++;
}
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;
    }
}
template < class T>
AutoPtr<T>::~AutoPtr()
{
    decrUser();
}
#endif // AUTOPTR_H

猜你喜欢

转载自blog.csdn.net/m0_50945459/article/details/121141844
今日推荐