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

C++ 实验三

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

C++ 实验三

目录
    • 一、实验内容
    • 二、代码实现
    • 1.queue.h
    • 2.queue.cpp
    • 3.main.cpp
    • 4.实验结果
    • 三、知识点总结
    • 1.模板的特化
    • 2.模板函数
    • 3.类模板
    • 4.const type& 与 type& 的区别
    • 5.operator<<>>运算符重载一定要为友元函数

一、实验内容

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

二、代码实现 1.queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include 
#include 

using namespace std;

//类模板:用于生成类
template class queue;
template class queueItem;
template class queueItem
{
    Type item;
    queueItem* next;
    queueItem(const Type& t) :item(0), next(0) {}
    friend class queue; //友元类,目的访问这里面的私有成员
    friend ostream& operator<<(ostream& os, const queue& q);
public:
    queueItem* operator++() {  //重载运算符++  用于指向队列里的下一个元素(指针类型)
        return next;
    }
    Type& operator*() { //重载运算符*  用于取队列里对应指针的值(取地址后 是Type类的)
        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&);
    void push(const Type&); //https://www.cnblogs.com/wss-is-knight/p/3624164.html
    void pop();
    bool empty() const {
        return head == 0;
    }
    ~queue() {  //析构函数
        destory();
    }
    Type& front() {//取队列头指针的值(取地址符)
        return head->item;
    }
    const Type& front() const { //返回值不能修改,并且不能修改对应对象中成员函数的值~
        return head->item;
    }
    friend ostream& operator<<(ostream& os, const queue& q) {  //https://blog.csdn.net/qq_36864672/article/details/76422722
        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 {//const no.1:避免返回值被修改  no.2:表示在函数内不能改变其对应对象的成员变量的值
        return (tail == NULL) ? NULL : tail->next;
    }
    //void copy_items(const queue &);
private:
    queueItem* head;
    queueItem* tail;
    void destory();
    void copy_items(const queue&);
    template void copy_items(It beg, It end);
};

templatevoid queue::destory()
{
    while (!empty()) {
        pop();
    }
}

templatevoid queue::pop()
{
    queueItem* p = head;
    head = head->next; //head虽然是私有变量,但是有friend升级
    delete p;
}

template void queue::push(const Type& val)
{
    queueItem* pt = new queueItem(val);//初始化并赋初值
    pt->item = val;
    if (empty()) {
        head = tail = pt;
        //cout << "success1" << endl;
    }
    else {
        tail->next = pt;
        tail = pt;
        //cout << "success2" << endl;
    }
}

template queue& queue::operator=(const queue& q)
{
    destory();
    copy_items(q);
}

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

template template void queue::assign(It beg, It end)
{
    destory();
    copy_items(beg, end);
}

template templatevoid queue::copy_items(It beg, It end)
{
    while (beg != end) {
        push(*beg);
        ++beg;
    }
}

templatevoid queue::copy_items(const queue& orig)
{
    for (queueItem* pt = orig.head; pt; pt = pt->next) {
        push(pt->item);
    }
}
template < >
void queue::push(const char* const& val);
template < >

void queue::pop();
template < >

int compare(const char* const& v1, const char* const& v2);
#endif // QUEUE_H


2.queue.cpp
#include "queue.h"
#include 

template<>  //对模板函数的特化
int compare(const char* const& v1, const char* const& v2)
{
	return strcmp(v1, v2);//因为字符串类型的不能直接==比较,所以需要特化一下~
}

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 (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;
}
3.main.cpp
#pragma once
#include "queue.h"
#include 

void TestQueue()
{
	queue qt;
	double d = 3.3;
	qt.push(1);
	qt.push(d);
	qt.push(10);
	cout << endl;
	cout << qt;
	
	short a[5] = { 0,3,6,9 };
	queue qi(a, a + 5);
	cout << endl;
	cout << qi;
	
	vector vi(a, a + 5);
	qi.assign(vi.begin(), vi.end());
	cout << endl;
	cout << qi;
	
	queue q1;
	q1.push("hi");
	q1.push("I'm");
	q1.push("fffffdy");
	cout << endl;
	cout << q1;
	
	queue q2(q1);
	cout << q2;
	
}

int main()
{
	TestQueue();
	return 0;
}
4.实验结果

三、知识点总结 1.模板的特化

函数模板特化:使用模板时会遇到一些特殊的类型需要特殊处理,不能直接使用当前的模板函数,所以此时我们就需要对该类型特化出一个模板函数(就是写出一个模板函数专门给该类型使用),比如:

template<>  //对模板函数的特化
int compare(const char* const& v1, const char* const& v2)
{
	return strcmp(v1, v2);//因为字符串类型的不能直接==比较,所以需要特化一下~
}

【注意】
*使用模板特化时,必须要先有基础的模板函数(就是上面第一个模板函数)
*使用特换模板函数时格式有要求:
1.template 后直接跟<> 里面不用写类型
2.函数名<特化类型>(特化类型 参数1, 特化类型 参数2 , …) 在函数名后跟<>其中写要特化的类型
*特化的函数的函数名,参数列表要和原基础的模板函数想相同,避免不必要的错误
*如果有能匹配的函数,则先使用特化函数

类模板特化:
全特化: 即将所有的模板类型都进行特化
偏特化:对于模板的类型做一些限制
a.部分特化:就是只对函数模板的一部分模板类型进行特化
b.对类型的范围的限制,主要的类型基础不变

template 
class Test{
}
//全特化
template <>  //此处同函数模板的特化一样不用写内容
class Test{
    
}


template 
class Test2{
}
//部分特化
template   //此处只需写未进行特化的模板类型,特化过的就不用写
class Test2{
    
}


template 
class Test2{
}
//对模板类型的范围做出一定的限制
template   //此处只需写未进行特化的模板类型
class Test2{
}

类的成员模板函数的特化:

template < >
void queue::push(const char* const& val);
template < >
void queue::pop();
2.模板函数

用于生成函数的
面向对象的继承和多态机制有效提高了程序的可重用性和可扩充性。在程序的可重用性方面,程序员还希望得到更多支持。就比如说写那个compare函数的时候,因为比较类型的不同(int,double,short等等)所以就需要写很多个重复的函数,这时候引入模板函数就很方便了~提高代码可读性!

3.类模板

有时,有两个或多个类,其功能是相同的,仅仅是数据类型不同,这个时候设计类模板就比较好用~
单个类模板:

 1 //类的类型参数化 抽象的类
 2 //单个类模板
 3 template
 4 class A 
 5 {
 6 public:
 7     A(T t)
 8     {
 9         this->t = t;
10     }
11 
12     T &getT()
13     {
14         return t;
15     }
16 protected:
17 public:
18     T t;
19 };
20 void main()
21 {
22    //模板了中如果使用了构造函数,则遵守以前的类的构造函数的调用规则
23     A  a(100); 
24     a.getT();
25     printAA(a);
26     return ;
27 }

继承的类模板:

 1 #include
 2 using namespace std;
 3 //A编程模板类--类型参数化
 4 
 7 template 
 8 class A
 9 {
10 public:
11     A(T a = 0)
12     {
13         this->a = a;
14     }
15 public:
16     void printA()
17     {
18         cout << "a:" << a << endl;
19     }
20 protected:
21 private:
22     T a;
23 };
24 //参数 C++编译器具体的类
25 void UseA(A &a)
26 {
27     a.printA();
28 }
29 void main()
30 {
31     //模板类本身就是抽象的,具体的类,具体的变量
32     A a1(11),a2(22),a3(33);//模板类是抽象的, 需要类型具体化
33     //a1.printA();
34 
35     UseA(a1);
36     UseA(a2);
37     UseA(a3);
38 }

4.const type& 与 type& 的区别

(1.int& 讲解
a的值可以通过a改变,也可以通过b改变

	int a = 10;
	int& b = a;

(2.const int& 讲解
a的值只能通过a改变,不能通过b改变

   int a = 10;
   const int& b = a;

(3.const int a = value 的引用只能为 const int b& = a
因为a的值是无法改变的,所以其引用也无法改变a的值,所以只能为常引用

5.operator<<>>运算符重载一定要为友元函数

如果是重载双目操作符(即为类的成员函数),就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身。
而 >> 或<< 左侧运算量是 cin或cout 而不是对象本身,所以不满足后面一点,嗯。。。就只能申明为友元函数了~

https://www.cnblogs.com/wss-is-knight/p/3624164.html
https://blog.csdn.net/low5252/article/details/94622335
https://www.cnblogs.com/hailong/articles/1977370.html
https://blog.csdn.net/alzzw/article/details/108150358
https://blog.csdn.net/qq_36864672/article/details/76422722

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

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

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