C++学习笔记:模板

  • 1.函数模板
  • 2.类模板
    • 2.1类模板注意事项
    • 2.2类模板中函数的创建时机
    • 2.3类模板对象作函数参数时
    • 2.4类模板与继承
    • 2.5类模板分文件编写
    • 2.6类模板友元
      • 2.6.1类内实现
      • 2.6.2类外实现
  • 3.例程

模板分为函数模板与类模板。


1.函数模板

函数模板可以建立一个通用的函数,其返回值和参数的类型无需提前确定,用一个虚拟的类型代表。
语法:

template<typename T>
//函数声明或定义
//template:表明创建一个模板
//typename:表明后面是一种数据类型
//T:通用数据类型

例程:

#include <iostream>
#include <string>
using namespace std;
template<typename T>
void myswap(T& a, T& b)
{T temp = a;a = b;b = temp;}
void test01()
{int a = 10;int b = 5;myswap(a, b);cout << "a:" << a << endl;cout << "b:" << b << endl;
}int main() {test01();return 0;
}

函数模板使用有两个注意点:
1.模板进行自动类型推导必须要推导出一致的数据类型T

#include <iostream>
#include <string>
using namespace std;
template<typename T>
void myswap(T& a, T& b)
{T temp = a;a = b;b = temp;}
void test01()
{int a = 10;int b = 5;char c = 'c';myswap(a, b);//正确myswap(a, c);//T类型不一致,错误cout << "a:" << a << endl;cout << "b:" << b << endl;
}int main() {test01();return 0;
}

2.模板必须要确定数据类型T才可使用

template<typename T>
void fun()
{cout<<"fun调用"<<endl;
}
fun<int>();//此时调用fun()需要进行显示指定类型

2.类模板

类模板可以建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型表示。
语法:

template<class T>
//后面写一个类

例程:

#include <iostream>
#include <string>
using namespace std;
template<typename nametype, typename agetype>
class Person
{public:nametype m_name;agetype m_age;Person(nametype name,agetype age){this->m_age = age;this->m_name = name;}void show(){cout << this->m_name << ":" << this->m_age << endl;}
};
void test01()
{Person <string, int>p1("Mike", 20);p1.show();
}int main() {test01();return 0;
}

2.1类模板注意事项

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

#include <iostream>
#include <string>
using namespace std;
template<typename nametype, typename agetype = int>
class Person
{public:nametype m_name;agetype m_age;Person(nametype name,agetype age){this->m_age = age;this->m_name = name;}void show(){cout << this->m_name << ":" << this->m_age << endl;}
};
void test01()
{//Person p1("Mike", 20);无法用自动类型推导Person<string,int> p1("Mike", 20);//显示类型推导p1.show();
}
void test02()
{Person<string> p1("Mike", 21);//agetype的类型为默认的intp1.show();
}int main() {test01();test02();return 0;
}

2.2类模板中函数的创建时机

普通类:一开始就创建;
类模板:成员函数在调用时才创建。

#include <iostream>
#include <string>
using namespace std;class Person1
{public:void showPerson1(){cout << "Person1调用" << endl;}};
class Person2
{public:void showPerson2(){cout << "Person2调用" << endl;}
};
//创建类模板
template<class T>
class myclass
{public:T obj;void fun1(){obj.showPerson1();}void fun2(){obj.showPerson2();}};void test01()
{myclass<Person1>p;p.fun1();//p.fun2();
}
void test02()
{myclass<Person2>p;//p.fun1();p.fun2();
}
int main()
{test01();test02();return 0;
}

2.3类模板对象作函数参数时

有三种方式将对象传入函数
1.指定传入类型,即显示推导数据的类型
2.参数模板化,传入具体的对象时确定了参数类型的对象时模板自动推导数据的类型;
3.整个类模板化传入

#include <iostream>
#include <string>
using namespace std;
//创建类模板
template<class T1,class T2>
class Person
{public:T1 name;T2 age;Person(T1 m_name,T2 m_age){this->age = m_age;this->name = m_name;}void showPerson(){cout << this->name << ":" << this->age << endl;}
};
//1.指定传入类型
void printPerson01(Person<string, int> &p)
{//在传入时确定模板的参数p.showPerson();
}
void test01()
{Person<string, int> p("Mike", 20);printPerson01(p);
}
//2.参数模板化
template<class T1, class T2>
void printPerson02(Person<T1, T2>& p)
{p.showPerson();cout << "T1类型为:" << typeid(T1).name() << endl;cout << "T2类型为:" << typeid(T2).name() << endl;
}
void test02()
{Person<string, int> p("Mike", 20);printPerson02(p);
}
//3.整个类模板化
template<class T>
void printPerson03(T& p)
{p.showPerson();cout << "T的数据类型为:" << typeid(T).name() << endl;
}
void test03()
{Person<string, int> p("Mike", 20);printPerson03(p);
}
int main()
{//test01();//test02();test03();return 0;
}

2.4类模板与继承

当父类是一个模板
1.子类直接继承时需要显示推导父类模板中的T的类型;
例程:

template<class T>
class base
{T m;
};
//class son :public base//错误,需要确定父类中T的类型
class Son1 :public base<int>
{};

2.如果需要灵活指定父类中的T数据类型,子类也需要变为模板;
例程:

template<class T>
class base
{T m;
};
//如果需要灵活指定父类的T类型,子类也需要变为模板
template<class T1, class T2>
class Son2 :public base<T2>
{T1 obj;
};

2.5类模板分文件编写

类模板函数在类外实现时要加前缀

template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age;
}

在分文件编写时,将含模板的类声明和实现写到一起,文件后缀名改为.hpp,例程如下。

//person.hpp文件
#pragma once
#include <iostream>
using namespace std;
#include <string>template<class T1, class T2>
class Person {public:Person(T1 name, T2 age);void showPerson();
public:T1 m_Name;T2 m_Age;
};//构造函数 类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age;
}//成员函数 类外实现
template<class T1, class T2>
void Person<T1, T2>::showPerson() {cout << "姓名: " << this->m_Name << " 年龄:" << this->m_Age << endl;
}

主函数如下:

#include<iostream>
using namespace std;
//将声明和实现写到一起,文件后缀名改为.hpp
#include "person.hpp"
void test01()
{Person<string, int> p("Tom", 10);p.showPerson();
}int main() {test01();system("pause");return 0;
}

2.6类模板友元

2.6.1类内实现

直接在类内声明友元即可,例程如下:

//全局函数,类内实现
//类内声明
friend void showPerson(Person<T1, T2>& p)
{cout << p.name << ":" << p.age << endl;
}void test01()
{Person<string, int>p("Tom", 20);showPerson(p);
}

2.6.2类外实现

需要提前让编译器得知全局函数的存在
在类前加入如下代码:

//声明类与函数
//声明类,同时该类是一个模板类
template<class T1, class T2>
class Person;
//声明函数,同时该函数是一个模板
template<class T1, class T2>
void showPerson1(Person<T1, T2>& p);

在类内声明时也要加空列表

//类外实现
friend void showPerson1<>(Person<T1, T2>& p);

类外调用

template<class T1, class T2>
void showPerson1(Person<T1, T2>& p)
{cout << p.name << ":" << p.age << endl;
}
void test02()
{Person<string, int>p("Tom", 21);showPerson1(p);
}

完整例程如下:

#include <iostream>
#include <string>
using namespace std;
//声明类与函数
//声明类,同时该类是一个模板类
template<class T1, class T2>
class Person;
//声明函数,同时该函数是一个模板
template<class T1, class T2>
void showPerson1(Person<T1, T2>& p);
//创建类模板
template<class T1, class T2>
class Person
{public:T1 name;T2 age;Person(T1 m_name, T2 m_age){this->age = m_age;this->name = m_name;}//全局函数,类内实现friend void showPerson( Person<T1, T2>& p){cout << p.name << ":" << p.age << endl;}//类外实现friend void showPerson1<>(Person<T1, T2>& p);};
void test01()
{Person<string, int>p("Tom", 20);showPerson(p);
}
//类外实现,需要加空模板参数,同时提前申明函数和类供编译器查询
template<class T1, class T2>
void showPerson1(Person<T1, T2>& p)
{cout << p.name << ":" << p.age << endl;
}
void test02()
{Person<string, int>p("Tom", 21);showPerson1(p);
}int main()
{//test01();test02();return 0;
}

3.例程

创建一个数组模板,实现如下功能
1.实现含参构造;
2.实现拷贝构造,深拷贝;
3.析构函数清理数据;
4.重载 = 避免浅拷贝;
5.可供下标查看数据;
6.可以进行append,pop等数组尾部增删操作。

mylist.hpp文件编写如下:

#pragma once
#include <iostream>
using namespace std;
#include <string>
template<class T>
class myarray
{public:myarray(int capacity){//构造函数this->m_capacity = capacity;this->m_size = 0;this->pAddress = new T[this->m_capacity];}myarray(const myarray& arr){//拷贝构造函数this->m_capacity = arr.m_capacity;this->m_size = arr.m_size;this->pAddress = new T[this->m_capacity];//深拷贝//数据拷贝for (int i = 0; i < this->m_size; i++){this->pAddress[i] = arr.pAddress[i];}}~myarray(){//析构函数if (this->pAddress != NULL){delete[] this->pAddress;this->pAddress = NULL;}}//operator= 防止浅拷贝myarray& operator=(const myarray& arr){//先判断原来的堆区是否有数据并释放if (this->pAddress != NULL){delete[] this->pAddress;this->pAddress = NULL;}this->m_capacity = arr.m_capacity;this->m_size = arr.m_size;this->pAddress = new T[this->m_capacity];//深拷贝for (int i = 0; i < arr.m_size; i++){this->pAddress[i] = arr.pAddress[i];}return *this;}void append(const T str){if (this->m_size >= this->m_capacity){cout << "数组已满" << endl;return;}else{this->pAddress[this->m_size] = str;this->m_size++;}}void pop(){if (this->m_size = 0){cout << "数组已空" << endl;return;}else{this->m_size--;}}T& operator[](int index){return this->pAddress[index];}int getcapacity(){return this->m_capacity;}int getsize(){return this->m_size;}private:T* pAddress;//指针指向堆区开辟的数组int m_capacity;//数组容量大小int m_size;//数组内元素个数
};

cpp文件编写如下:

#include <iostream>
#include <string>
using namespace std;
#include"mylist.hpp"void printarray(myarray<int>& p)
{for (int i = 0; i < p.getsize(); i++){cout << p[i] << endl;}
}
void test01()
{myarray<int>arr1(5);arr1.append(1);arr1.append(2);arr1.append(3);arr1.append(4);arr1.append(5);printarray(arr1);
}
int main()
{test01();return 0;
}

C++学习笔记:模板相关推荐

  1. 设计模式学习笔记——模板(Template)模式

    设计模式学习笔记--模板(Template)模式 @(设计模式)[设计模式, 模板模式, template, 模板方法] 设计模式学习笔记模板Template模式 基本介绍 模板案例 类图 实现代码 ...

  2. 图论01.最短路专题_学习笔记+模板

    图论01.最短路专题_学习笔记+模板 一.定义与性质 ● 需要的前导知识点 路径 最短路 有向图中的最短路.无向图中的最短路 单源最短路.每对结点之间的最短路 ● 最短路的性质 对于边权为正的图,任意 ...

  3. image是否有disabled属性_Vue学习笔记 模板语法、计算属性

    点击上方"蓝字"关注我们吧! vue学习笔记 官网:https://cn.vuejs.org/v2/guide/ 1.vue体验 demo示例: image.png 示例代码: & ...

  4. C++模板学习笔记——模板实参

    对于函数模板,编译器通过隐式推断模板实参.其中,从函数实参来确定模板实参的过程被称为模板实参推断.在模板实参推断过程中,编译器使用函数调用中的实参类型来寻找模板实参,用这些模板实参生成的函数版本与给定 ...

  5. C++学习笔记—模板与STL

    C++提高编程 本阶段主要针对C++泛型编程和STL技术做详细讲解,探讨C++更深层的使用 1 模板 1.1 模板的概念 模板就是建立通用的模具,大大提高复用性 例如生活中的模板 一寸照片模板 PPT ...

  6. C++学习笔记-------模板(template)

    文章目录 1.函数模板 2.类模板 2.1类模板的基本使用 2.2类模板中的友元 3.模板默认参数 3.1模板函数的默认参数 3.2类模板默认参数 4.成员模板 4.1普通类的成员模板 4.2模板类的 ...

  7. [C++]学习笔记——模板

    针对C++泛型编程和STL技术做详细讲解,探讨C++更深层的使用. 1.模板 1.1模板的概念 模板就是建立通用的模具,大大提高复用性 日常生活例子帮助理解:一寸照片模板.PPT模板 1.2函数模板语 ...

  8. LearnOpenGL学习笔记——模板测试

    模板测试 当片段着色器处理完一个片段之后,模板测试(Stencil Buffer)会开始执行,和深度测试一样,它也可能会丢弃片段.接下来,被保留的片段会进入深度测试,它可能会丢弃更多的片段.模板测试是 ...

  9. dx12 龙书第十一章学习笔记 -- 模板

    模板缓冲区是一种"离屏"(off-screen)缓冲区,我们可以用它来实现一些特殊的效果.模板缓冲区.后台缓冲区以及深度缓冲区都有着相同的分辨率,所以三者相同位置上的像素就能一一对 ...

最新文章

  1. vscode如何用浏览器预览运行html文件
  2. JavaScript中this指向
  3. ie浏览器升级_微软呼吁用户停用IE浏览器 2020年将不再更新升级
  4. 2021年即墨萃英中学高考成绩查询,2017即墨萃英中学青岛十九中录取分数线发布...
  5. 安卓端华为推送集成笔记
  6. easyui中动态使datebox、combobox为只读状态
  7. Oracle如何建立多库,基于Oracle多库查询方法(分享)
  8. linux搭建LAMP架构服务
  9. outlook搜索栏跑到上面去了_南昌搜索引擎seo优化
  10. MAC打开eclipse一直卡在core.ui的解决办法
  11. 结构体定义LNode,*LinkList和typedef struct
  12. 大话卫星导航中的信号处理系列文章——目录
  13. 【盘点大系】《盘点5月份--2018》
  14. Python不使用科学计数法输出数据的实现方法
  15. Android 调用相机闪退问题
  16. Quagga简介、安装、配置说明
  17. i5 11300h和r5 4600h的差别大吗
  18. 重装win10之后,双系统grub消失,ubuntu无法进入,(ubuntu的grub引导损坏)解决方法
  19. Quant进阶:用『最少』的数学,学『最全』的图神经网络
  20. win+r中的cmd作用

热门文章

  1. Sql server 2008镜像配置步骤
  2. [奥运] 冠军的付出与回报
  3. 智能电动牙刷PCBA板
  4. 原创-linux测试篇- linux如何使用dd命令对 硬盘 U盘进行测试读写速度(详细讲解图表)
  5. imadjust使用opencv实现
  6. Oracle SQL 劈开字符串
  7. 腾讯云tca架构师认证题库
  8. MySQL的主动优化和被动优化_不要一把梭了,这才是SQL优化的正确姿式!|原创干货...
  9. 2012计算机二级成绩,2012年全国计算机二级考试成绩查询
  10. win7用什么版本linux系统版本,想学Linux系统,具体哪一个版本的平稳,在win7下装的...