C++实验三(模板)

一模板函数

1 一般模板函数

1.1代码实现

template <class T>
int compare(const T& left, const T& right)
{
    if (left < right) return -1;
    else if (left > right) return 1;
    else return 0;
}
template <class T,int size>
int compare(T(&v1)[size], T(&v2)[size])
{
    for (int i = 0; i <= size;i++)
    {
        if (v1[i] > v2[i]) return 1;
        else if (v1[i] < v2[i]) return -1;
   }
    return 0;
}

int main(int argc, char** argv) {
   cout<< compare(1, 2)<<endl;
   cout << compare(2.5,3.6)<<endl;
   cout << compare("aab","aac")<<endl;
   const char* a = "aab";
   const char* b = "aaa";
   cout << compare(a, b);

}

1.2 运行截图

在这里插入图片描述

1.3 小结

显然我们可以用该一般模板函数进行大部分同类型数值的比较,template <class T>用于单个数据,而template <class T,int size>用于数组,但当类型为const char*时通过该函数简单的< > =是无法对这种特殊类型数值大小进行正确比较,所以大部分类型比较用一般模板函数即可,而特殊的类型比较应该用特化模板函数。

2 特化模板函数

2.1 代码实现

#include  < iostream>
#include <stdio.h>
#include<malloc.h>
#include "CMatrix.h"
using namespace std;
template <class T>
int compare(const T& left, const T& right)
{
    if (left < right) return -1;
    else if (left > right) return 1;
    else return 0;
}
template <class T,int size>
int compare(T(&v1)[size], T(&v2)[size])
{
    for (int i = 0; i <= size;i++)
    {
        if (v1[i] > v2[i]) return 1;
        else if (v1[i] < v2[i]) return -1;
   }
    return 0;
}
template < >
int compare<const char*>(const char* const& v1, const char* const& v2)
{
    return strcmp(v1, v2);
}
int main(int argc, char** argv) {
   cout<< compare(1, 2)<<endl;
   cout << compare(2.5,3.6)<<endl;
   cout << compare("aab","aac")<<endl;
   const char* a = "aab";
   const char* b = "aaa";
   cout << compare(a, b);

}

2.2 运行截图

在这里插入图片描述

2.3 小结

template<class T>
int compare(const T& left, const T& right)
  template <class T,int size>
int compare(T(&v1)[size], T(&v2)[size])
template < >
int compare<const char*>(const char* const& v1, const char* const& v2)
{
    return strcmp(v1, v2);
}

3个compare的模板函数已经可以比较好的解决绝大部分数据的正确比较。

二 模板类Queue或Stack

1 模板类

1.1 代码实现

queue.h文件:

#ifndef QUEUE_H
#define QUEUE_H
#include <iostream> 
using namespace std;
//定义类模板
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 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(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);
};
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指针指向该元素
        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);
}
template<class Type> template<class It> void Queue<Type>::copy_items(It beg, It end)
{
    while (beg != end) {
        push(*beg);
        ++beg;
    }
}
//销毁队列
template<class Type>
void Queue<Type>::destroy()
{
    while (!empty()) {
        pop();
    }
}
void TestQueue();
#endif

main.cpp文件:

#include<iostream>
#include "queue.h"
using namespace std;
int main() {
    Queue<int> qt;
    qt.push(8);
    qt.push(6);
    qt.push(2);
    cout << qt;
    return 0;
}

1.2运行截图

在这里插入图片描述

1.3 小结

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

2 成员模板函数

2.1代码实现

实现代码

//成员模板函数的实现
template <class It>
Queue(It beg, It end) : head(0), tail(0) { 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;
    }
}

测试代码

 int a[5] = { 1,2,3,4,5 };
    Queue<int> q(a,a+5);
    cout << q;

2.2运行截图

在这里插入图片描述

2.3 小结

通过成员模板函数让该类的适用性更强,让类中的一个函数可以处理多种类型参数变量。

3 模板特化

3.1 代码实现

具体实现

template <>
void Queue<const char*>::push(const char* const& val) {
    char* new_item = new char[strlen(val) + 1];
    //将val的值赋值到new_item,其中strlen(val)为需要复制的长度
    strncpy_s(new_item,strlen(new_item),val, strlen(val));
    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;
}

测试代码


	Queue<const char*> q1;
	q1.push("www");
	q1.push("hhc");
	q1.push("6666");
	cout << q1;

3.2 运行截图

在这里插入图片描述

3.3 小结

特殊类型可以调用模板特化函数来实现一般模板不能实现的效果。

三 模板类AutoPtr

1 代码实现

具体实现

#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);
    //用户数减1
    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;
    //用户数加1
    (*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

测试代码

AutoPtr<CMatrix> h1(new CMatrix);
    double data[10] = { 1,2,3,4,5,6,7,8,9,10 };
    //生成一个2行5列的数组
    h1->Create(2, 5, data);
    cout << *h1 << endl;
    //h2(拷贝构造函数的使用)和h1指向的是同一个地方
    AutoPtr<CMatrix> h2(h1);
    (*h2).Set(0, 1, 10);
    cout << *h1 << *h2 << endl;

2 运行截图

在这里插入图片描述

3 小结

AutoPtr类似于Java中对象管理机制的智能指针类,它能够实时监测对象的用户数量,并控制其生命周期的结束(当对象的用户数为0时释放该对象所占用的内存)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴为您回答这个问题。以下是关于C++模板与异常的实验报告: 一、实验目的 通过实验,掌握C++模板和异常的使用方法,提高编程技能。 二、实验内容 1. 实现一个模板类,可以实现数组的基本操作,并能够处理异常情况。 2. 实现一个函数模板,可以实现两个数的交换,并能够处理异常情况。 三、实验步骤及方法 1. 实现模板类 (1)定义一个模板类,包含数组的大小和指向数组元素的指针。 (2)实现数组基本操作,包括初始化数组、释放数组、获取数组元素等。 (3)使用try-catch语句,处理数组越界的异常情况。 2. 实现函数模板 (1)定义一个函数模板,可以实现两个数的交换。 (2)使用try-catch语句,处理类型不匹配的异常情况。 四、实验结果 1. 实现模板模板类的定义如下: ```c++ template<typename T> class Array { public: Array(int size); ~Array(); T & operator[](int i); private: T * m_ptr; int m_size; }; ``` 模板类的实现如下: ```c++ template<typename T> Array<T>::Array(int size) { m_size = size; m_ptr = new T[size]; } template<typename T> Array<T>::~Array() { delete [] m_ptr; } template<typename T> T & Array<T>::operator[](int i) { if (i < 0 || i >= m_size) { throw std::out_of_range("Index out of range."); } return m_ptr[i]; } ``` 2. 实现函数模板 函数模板的定义如下: ```c++ template<typename T> void swap(T & a, T & b); ``` 函数模板的实现如下: ```c++ template<typename T> void swap(T & a, T & b) { T temp = a; a = b; b = temp; } ``` 五、实验总结 通过本次实验,我学会了如何使用C++模板和异常,这对我的编程技能提高有很大帮助。同时,我也发现了异常处理的重要性,可以有效地避免程序崩溃的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值