IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++】实验3 模板 -> 正文阅读

[C++知识库]【C++】实验3 模板

目录

实验内容

实验过程

一、模板函数

1.一般模板函数

2.特化模板函数(模板函数只有全特化,没有偏特化)

?二、模板类

三、模板类AutoPtr

1.构造函数

2.析构函数

3.拷贝构造函数

4.等号、->、*等运算符重载

5.主函数调用AutoPtr

总结?

一、函数模板

二、类模板

三、模板类AutoPtr


实验内容

一、模板函数
一般模板函数
特化模板函数

二、模板类
模板类
成员模板函数
模板特化:模板成员函数特化、模板类特化

三、模板类AutoPtr
构造函数
析构函数
拷贝构造函数
等号、->、*等运算符重载
主函数调用AutoPtr

实验过程

一、模板函数

1.一般模板函数

模板函数定义:所谓模板函数,实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。

模板函数的写法

template <class/typename 类型参数1, class/typename 类型参数2, ...>
返回值类型  模板函数名(形参表)
{
    函数体
}

一个模板函数例子(交换参量的Swap模板函数)

#include <iostream>
using namespace std;
template<class T>
void Swap(T &x, T &y)
{
	T tmp = x;
	x = y;
	y = tmp;
}

int main()
{
    int n = 1, m = 2;
    Swap(n, m);  //编译器自动生成 void Swap (int &, int &)函数
    cout<<n<<"\n"<<m<<endl;
    double f = 1.1, g = 2.2;
    Swap(f, g);  //编译器自动生成 void Swap (double &, double &)函数
    cout<<f<<"\n"<<g<<endl;
    return 0;
}

T 是类型参数,代表类型。编译器由模板自动生成函数时,会用具体的类型名对模板中所有的类型参数进行替换,其他部分则原封不动地保留。同一个类型参数只能替换为同一种类型。编译器在编译到调用函数模板的语句时,会根据实参的类型判断该如何替换模板中的类型参数。

运行结果

函数模板是用于生成函数的,像上面的例子,可以只写一个 Swap 模板,编译器会根据 Swap 模板自动生成多个 Sawp 函数,用以交换不同类型变量的值。

2.特化模板函数(模板函数只有全特化,没有偏特化)

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

我们先写一个模板函数compare()

template <class T>
int compare(const T &left, const T&right)
{
    cout <<"in template<class T>..." <<endl;
    return (left - right);
}

这个模板函数它支持常见int, double,float等类型的数据的比较,但是它不支持char*(string)类型的比较,因此我们必须对其进行特化,以让它支持两个字符串的比较,因此我们实现了如下的特化函数。

template < >
int compare(const char* left, const char* right)
{
    cout <<"in special template< >..." <<endl;

    return strcmp(left, right);
}

特化后的模版函数compare()现在就支持char*(string)类型的比较。

测试代码

#include <iostream>
#include <string.h>
using namespace std;

//函数模板
template <class T>
int compare(const T left, const T right)
{
    cout <<"in template<class T>..." <<endl;
    return (left - right);
}


//  这个是一个特化的函数模版
template < >
int compare(const char* left, const char* right)
{
    cout <<"in special template< >..." <<endl;
    return strcmp(left, right);
}


int main( )
{
    
    cout<<compare(1, 4)<<endl;     //int 类型的比较

    cout<<compare(8.8,1.1)<<endl;  //double 类型的比较

    const char *left = "longer";
    const char *right = "long";
    
    cout<<compare(left, right)<<endl;   //string 类型的比较

    return 0;
}

?运行结果

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

?二、模板类

模板类的定义:类模板,可以定义相同的操作,拥有不同数据类型的成员属性。 通常使用 template 来声明。 告诉编译器,碰到 T 不要报错,表示一种泛型. 普通模板函数和友元模板函数,声明和定义都写在类的内部,也不会有什么报错。

模板类的写法?

template  <类型形参表>
 class  <类名>
 {     //类说明体  };
 template  <类型形参表>
 <返回类型> <类名> <类型名表>::<成员函数1>(形参表)
 {     //成员函数定义体  }
 template  <类型形参表>
 <返回类型> <类名> <类型名表>::<成员函数2>(形参表)
 {     //成员函数定义体  }
 …
 template  <类型形参表>
 <返回类型> <类名> <类型名表>::<成员函数n>(形参表)
 {     //成员函数定义体  }

?模板类的全特化与偏特化

#include <iostream>
using namespace std;
template<typename T1, typename T2>
class Test
{
public:
	Test(T1 i,T2 j):a(i),b(j){cout<<"模板类"<<endl<<a<<" "<<b<<endl;}
private:
	T1 a;
	T2 b;
};
 
template<>
class Test<int , char>
{
public:
	Test(int i, char j):a(i),b(j){cout<<"全特化"<<endl<<a<<" "<<b<<endl;}
private:
	int a;
	char b;
};
 
template <typename T2>
class Test<char, T2>
{
public:
	Test(char i, T2 j):a(i),b(j){cout<<"偏特化"<<endl<<a<<" "<<b<<endl;}
private:
	char a;
	T2 b;
};

int main()
{
	Test<double,int> t1(1.1,2);    //调用一般模板类
	Test<int , char> t2(1,'A');    //调用全特化模板类
	Test<char, bool> t3('A',false);  //调用偏特化模板类
    cout<<a<<b<<endl;
	return 0;
} 

运行结果

成员模板函数

定义:成员函数模板是类或类模板的成员的模板函数。 成员函数可以是多个环境中的函数模板。 类模板的所有函数都是泛型的,但却不称为成员模板或成员函数模板。 如果这些成员函数采用其自己的模板自变量,则将它们视为成员函数模板。

#include <iostream>
using namespace std;
template <typename T>
class Test
{
public:
	template <typename R>
	void Swap(R &i, R &j){R tmp; tmp = i;i = j;j = tmp;}    //模板成员函数 

};
 


int main()
{
    Test <int> t;
	double m=1.1,n=2.2;
	t.Swap(m,n);
	cout<<m<<" "<<n<<endl;
	return 0;
} 

模板成员函数特化

#include <iostream>
using namespace std;
template <typename T>
class Test
{
public:
	template <typename R>
	void Swap(R &i, R &j){R tmp; tmp = i;i = j;j = tmp;}    //模板成员函数 
    void Swap(int &i, double &j){int tmp;tmp=i;i=j;j=tmp;cout<<"特化的Swap"<<endl;} //模板成员函数特化
	
};
 


int main()
{
    Test <int> t;
	double m=1.1,n=2.2;
	t.Swap(m,n);              //调用一般的模板成员函数
	cout<<m<<" "<<n<<endl;    //调用特化的模板成员函数
	int a=10;
	double b=1.33;
	t.Swap(a,b);
	cout<<a<<" "<<b<<endl;
} 

运行结果

三、模板类AutoPtr

1.构造函数

template<class T>
AutoPtr<T>::AutoPtr(T* pData)
{
	m_pData = pData;
	m_nUser = new int(1);
}

2.析构函数

~AutoPtr()
	{
		decrUser();
	}
void decrUser();
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;
	}
}

3.拷贝构造函数

template<class T>
AutoPtr<T>::AutoPtr(const AutoPtr<T>& h)
{
	m_pData = h.m_pData;
	m_nUser = h.m_nUser;
	(*m_nUser)++;
}

4.等号、->、*等运算符重载

AutoPtr<T>& operator=(const AutoPtr<T>& h);
T* operator->()
{
	return m_pData;
}
T& operator*()
{
	return *m_pData;
}
const T& operator *()const
{
	return *m_pData;
}
const T* operator ->()const
{
	return m_pData;
}
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)++;
}

5.主函数调用AutoPtr

#include<iostream>
#include <vector>
#include "autoptr.h"
#include "CMatrix.h"
using namespace std;
int main()
{
    AutoPtr<CMatrix> h1;
    double data[6] = {1,2,3,4,5,6};
    h1->Create(2,3,data);
    cout << *h1 << endl;
    AutoPtr<CMatrix> h2(h1);
    (*h2).Set(0,1,10);
    cout << *h1 << endl << *h2;
}

运行结果

总结?

一、函数模板

1、函数模板利用关键字template
2、使用函数模板有两种方式:自动类型推到、显示指定类型
3、模板的目的是为了提高复用性,将类型参数化

注意事项:
1、自动类型推导,必须推导出一致的数据类型T,才可以使用
2、模板必须要确定出T的数据类型,才可以使用

普通函数和函数模板的调用规则:
1、如果函数模板和普通函数都可以实现,优先调用普通函数
2、可以通过空模板参数列表来强制调用函数模板 。 如:myPrint<>(a, b); //<>里不用写东西
3、函数模板也可以发生重载。 重载后不加<>直接调用 如:myPrint(a, b, c);
4、如果函数模板可以产生更好的匹配,优先调用函数模板

一般来说,既然提供了函数模板,最好就不要提供普通函数,否则容易出现二义性。

二、类模板

类模板和函数模板区别主要有两点:
1、类模板没有自动类型推导的使用方式
2、类模板在模板参数列表中可以有默认参数
如:template<class NameType,class AgeType = int>
那么在创建对象的时候就不用指定int类型,如:Person< string > p2(“张三”, 99);

类模板中成员函数和普通类中成员函数创建时机的区别:
1、普通类中的成员函数一开始就创建
2、类模板中的成员函数在调用时才创建

类模板对象做函数参数,即类模板实例化出对象,向函数传参的方式,一共有三种传入方式:
1、指定传入的类型:直接显示对象的数据类型 ( 最常用第一种)
2、参数模板化:将对象中的参数变为模板进行传递
3、整个类模板化:将这个对象类型 模板化进行传递

类模板与继承
1、当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
2、如果不指定,编译器无法给子类分配内存
3、如果想灵活指定出父类中T的类型,子类也需要变为类模板

类模板分文件编写
问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:
1、直接包含.cpp文件
2、将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制
?

三、模板类AutoPtr

new和delete的作用:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针,delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存。

动态内存管理经常会出现两种问题:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????一种是忘记释放内存,会造成内存泄漏;一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针。? ? ? ? ? ? ? ? ? ? ??

智能指针的概念:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????为了更加容易(更加安全)的使用动态内存,引入了智能指针的概念。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-18 11:01:39  更:2021-11-18 11:03:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:42:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码