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

C++实验三(模板)

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

C++实验三(模板)

目录
  • 一模板函数
    • 1 一般模板函数
      • 1.1代码实现
      • 1.2 运行截图
      • 1.3 小结
    • 2 特化模板函数
      • 2.1 代码实现
      • 2.2 运行截图
      • 2.3 小结
  • 二 模板类Queue或Stack
    • 1 模板类
      • 1.1 代码实现
      • 1.2运行截图
      • 1.3 小结
    • 2 成员模板函数
      • 2.1代码实现
      • 2.2运行截图
      • 2.3 小结
    • 3 模板特化
      • 3.1 代码实现
      • 3.2 运行截图
      • 3.3 小结
  • 三 模板类AutoPtr
    • 1 代码实现
    • 2 运行截图
    • 3 小结

一模板函数 1 一般模板函数 1.1代码实现
template 
int compare(const T& left, const T& right)
{
    if (left < right) return -1;
    else if (left > right) return 1;
    else return 0;
}
template 
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)< 
1.2 运行截图 

1.3 小结

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

2 特化模板函数 2.1 代码实现
#include  < iostream>
#include 
#include
#include "CMatrix.h"
using namespace std;
template 
int compare(const T& left, const T& right)
{
    if (left < right) return -1;
    else if (left > right) return 1;
    else return 0;
}
template 
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& v1, const char* const& v2)
{
    return strcmp(v1, v2);
}
int main(int argc, char** argv) {
   cout<< compare(1, 2)< 
2.2 运行截图 

2.3 小结
template
int compare(const T& left, const T& right)
  template 
int compare(T(&v1)[size], T(&v2)[size])
template < >
int compare(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  
using namespace std;
//定义类模板
template class Queue;
template class QueueItem {
    QueueItem(const Type& t) : item(t), next(0) {}
    Type item;
    QueueItem* next;
    friend class Queue;
    //输出运算符的重载
    friend ostream& operator<<(ostream& os, const Queue& q);
    QueueItem* operator++() {
        return next;
    }
    Type& operator*() {
        return item;
    }
};
template class Queue {
public:
    Queue() : head(0), tail(0) {}
    Queue(const Queue& q) : head(0), tail(0) {
        copy_items(q);
    }
    //成员函数模板
    template 
    Queue(It beg, It end) : head(0), tail(0) { copy_items(beg, end); }
    template 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& q) {
        os << "< ";
        QueueItem* p;
        for (p = q.head; p; p = p -> next) {
            os << p->item << " ";
        }
        os << ">";
        return os;
    }
    const QueueItem* Head() const { return head; }
    const QueueItem* End() const { return (tail == NULL) ? NULL : tail -> next; }
private:
    QueueItem* head;
    QueueItem *tail;
    void destroy();
    void copy_items(const Queue&);
    template
    void copy_items(It beg, It end);
};
template
void Queue::pop() {
    QueueItem* p = head;
    head = head -> next;
    delete p;
}
template 
void Queue::push(const Type& val) {
    QueueItem* pt = new QueueItem(val);
    if (empty()) {
        head = tail = pt;
    }
    else {
        tail -> next = pt;
        //元素添加到队列后tail指针指向该元素
        tail = pt; 
    }
}
template < >
void Queue::push(const char* const& val);
template < >
void Queue::pop();
template 
void Queue::copy_items(const Queue& orig) {
    for (QueueItem* pt = orig.head; pt; pt = pt -> next) {
        push(pt -> item);
    }
}
template 
Queue& Queue::operator=(const Queue& q)
{
    destroy();
    copy_items(q);
}
template template void Queue::assign(It beg, It end)
{
    destroy();
    copy_items(beg, end);
}
template template void Queue::copy_items(It beg, It end)
{
    while (beg != end) {
        push(*beg);
        ++beg;
    }
}
//销毁队列
template
void Queue::destroy()
{
    while (!empty()) {
        pop();
    }
}
void TestQueue();
#endif

main.cpp文件:

#include
#include "queue.h"
using namespace std;
int main() {
    Queue qt;
    qt.push(8);
    qt.push(6);
    qt.push(2);
    cout << qt;
    return 0;
}
1.2运行截图

1.3 小结

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

2 成员模板函数 2.1代码实现

实现代码

//成员模板函数的实现
template 
Queue(It beg, It end) : head(0), tail(0) { copy_items(beg, end); 
}
//成员模板函数的实现
template 
template 
void Queue::copy_items(It beg, It end)
{
    while (beg != end) {
        //将数组中下标对应的值添加到队列中
        push(*beg);
        ++beg;
    }
}

测试代码

 int a[5] = { 1,2,3,4,5 };
    Queue q(a,a+5);
    cout << q;
2.2运行截图

2.3 小结

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

3 模板特化 3.1 代码实现

具体实现

template <>
void Queue::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* pt = new QueueItem(new_item);
    if (empty()) {
        head = tail = pt;
    }
    else {
        tail->next = pt;
        tail = pt;
    }
}
template <>
void Queue::pop() {
    QueueItem* p = head;
    delete head->item;
    head = head->next;
    delete p;
}

测试代码

	Queue 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 AutoPtr
{
public:
    //构造函数
    AutoPtr(T* pData);
    //拷贝构造函数
    AutoPtr(const AutoPtr& h);
    //声明周期结束时调用析构函数
    ~AutoPtr();
    //等号的重载
    AutoPtr& operator=(const AutoPtr& 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::AutoPtr(T* pData)
{
    m_pData = pData;
    //初始化用户数为1
    m_nUser = new int(1);
}
template < class T>
AutoPtr::AutoPtr(const AutoPtr& h) {
    m_pData = h.m_pData;
    m_nUser = h.m_nUser;
    //用户数加1
    (*m_nUser)++;
}
template < class T>
AutoPtr& AutoPtr::operator=(const AutoPtr& h)
{
    decrUser();
    m_pData = h.m_pData;
    m_nUser = h.m_nUser;
    (*m_nUser)++;
}
template < class T>
void AutoPtr::decrUser()
{
    --(*m_nUser);
    if ((*m_nUser) == 0) {
        //删除数据
        delete m_pData;
        //地址赋为空
        m_pData = 0;
        delete m_nUser;
        m_nUser = 0;
    }
}
template < class T>
AutoPtr::~AutoPtr()
{
    decrUser();
}
#endif // AUTOPTR_H

测试代码

AutoPtr 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 h2(h1);
    (*h2).Set(0, 1, 10);
    cout << *h1 << *h2 << endl;
2 运行截图

3 小结

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

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

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

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