当前位置: 首页 > news >正文

typename、非类型模板参数、模板参数的特化、模板类成员函数声明和定义分离、继承等的介绍

文章目录

  • 前言
  • 一、typename
  • 二、非类型模板参数
  • 三、模板参数的特化
    • 1. 函数模板参数的特化
    • 2. 类模板的特化
  • 四、模板类成员函数声明和定义分离
    • 1. 显示实例化(不建议使用)
    • 2. 将生命和定义写在同一个.h文件中
  • 五、 继承
  • 总结


前言

typename、非类型模板参数、模板参数的特化、模板类成员函数声明和定义分离、继承等的介绍


一、typename

void Print(vector<int>& v)
{vector<int>::iterator it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;
}

对上述Print函数进行模板化,如果不加typename会出现如下情况:
在这里插入图片描述

#include <iostream>
#include <vector>
#include <list>
using namespace std;template <class Container>
void Print(Container& v)
{typename Container::iterator it = v.begin(); // 此处要加typename修饰while (it != v.end()){cout << *it << " ";++it;}cout << endl;
}
int main()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);Print(v);vector<double> v1;v1.push_back(1.1);v1.push_back(2.2);v1.push_back(3.3);v1.push_back(4.4);v1.push_back(5.5);Print(v1);list<double> lt;lt.push_back(1.14);lt.push_back(2.14);lt.push_back(3.14);lt.push_back(4.14);lt.push_back(5.14);Print(lt);return 0;
}

在这里插入图片描述

二、非类型模板参数

  • 比如一个静态栈,不仅需要接收类型参数, 还需要接收每个数组的长度
#include <iostream>
#include <vector>
#include <list>
using namespace std;// 静态栈
template <class T, size_t N>
class Stack
{
public:Stack(){}
private:T _a[N];int _top;
};
int main()
{Stack<int, 10> st1; // 10Stack<double, 100> st2; // 100return 0;
}

在这里插入图片描述

三、模板参数的特化

特化指的就是 特殊化处理

1. 函数模板参数的特化

  • 函数模板个格式,虽然需要加template<>,但是大多数情况下,我们可以直接去掉,与原来的函数构成函数重载,达到特化的效果
#include <iostream>
using namespace std;
// 函数模板的特化
template <class T>
bool Less(T left, T right)
{return left < right;
}// 函数模板的特化格式
template<>
bool Less<int*>(int* left, int* right)
{return *left < *right;
}int main()
{cout << Less(1, 2) << endl;int a = 2, b = 1;cout << Less(&a, &b) << endl;return 0;
}

在这里插入图片描述

2. 类模板的特化

类模板的特化包括 全特化,偏特化(半特化), 限制类型为指针, 限制类型为引用

#include <iostream>
using namespace std;// 类模板特化template <class T1, class T2>
class A
{
public:A() { cout << "A<T1, T2>" << endl; }
private:
};// 全特化
template<>
class A<int, double>
{
public:A() { cout << "A<int, double>" << endl; }
private:
};// 偏特化
template <class T1>
class A<T1, double>
{
public:A() { cout << "A<T1, double>" << endl; }
private:
};// 对类型进行限制---指针
template <class T1, class T2>
class A<T1*, T2*>
{
public:A() { cout << "A<T1*, T2*>" << endl; }
private:
};// 对类型限制---引用
template <class T1, class T2>
class A<T1&, T2&>
{
public:A() { cout << "A<T1&, T2&>" << endl; }
private:
};int main()
{A<int, int> a1;A<int, double> a2;A<double, double> a3;A<char, double> a4;A<int*, double> a5;A<int*, double*> a6;A<void*, void*> a7;A<int&, double&> a8;return 0;
}

在这里插入图片描述

四、模板类成员函数声明和定义分离

模板类成员函数声明和定义分离 有两种方式:
一种是: 在函数的定义处显示实例化
另一种是: 将生命和定义写在同一个.h文件中,(有些还将这种文件以.hpp作为后缀)

模板类成员函数声明和定义直接分离,因为模板类型T没有进行实例化,编译器在链接阶段无法找到正确的地址,所以会出现编译报错。

1. 显示实例化(不建议使用)

// Stack.h
#pragma once
#include <vector>namespace hhb
{template<class T, class Container = std::vector<T>>class stack{public:void push(const T& x);void pop();bool empty(){return _con.empty();}const T& top(){return _con.front();}private:Container _con;};}

// Stack.cpp
#include "Stack.h"namespace hhb
{template<class T, class Container>void stack<T, Container>::push(const T& x){_con.push_back(x);}template <class T, class Container>void stack<T, Container>::pop(){_con.pop_back();}templateclass stack<int>;templateclass stack<double>;
}

// test.cpp
#include "Stack.h"int main()
{hhb::stack<int> st;st.push(1);st.pop();hhb::stack<double> st1;st1.push(1.1);st1.pop();return 0;
}
  • 不会有编译错误

2. 将生命和定义写在同一个.h文件中

// Stack.h
#pragma once
#include <vector>namespace hhb
{template<class T, class Container = std::vector<T>>class stack{public:void push(const T& x);void pop();bool empty(){return _con.empty();}const T& top(){return _con.front();}private:Container _con;};template<class T, class Container>void stack<T, Container>::push(const T& x){_con.push_back(x);}template <class T, class Container>void stack<T, Container>::pop(){_con.pop_back();}}

// test.cpp
#include "Stack.h"int main()
{hhb::stack<int> st;st.push(1);st.pop();hhb::stack<double> st1;st1.push(1.1);st1.pop();return 0;
}
  • 不会有编译错误

五、 继承

访问限定符的权限 : public > protected > privated;
继承是有基类以继承方式继承给派生类
继承方式: 有三种 以 public 、 protected、 private 三种方式进行继承。
派生类对基类成员变量/成员函数的访问方式取决于: 基类的成员变量和成员函数的访问限定符以及派生类的继承方式:

  1. 基类的成员若为private, 则在派生类中无法看见(访问)基类private的成员
  2. 基类的protected和public成员, 与派生类的继承方式权限进行比较,权限小的即为在派生类中访问基类成员的访问方式。
#include <iostream>
using namespace std;
class Person
{
public:Person(){}void print(){cout << "_name: " << _name <<  endl;cout << "_age: " << _age << endl;}
protected:string _name = "perter";int _age = 10;
};class student : public Person
{
public:
private:int _sid;
};class teacher : public Person
{
public:
private:int _tid;
};int main()
{student s;s.print();teacher t;t.print();return 0;
}

在这里插入图片描述

总结

typename、非类型模板参数、模板参数的特化、模板类成员函数声明和定义分离、继承等的介绍


http://www.mrgr.cn/news/34733.html

相关文章:

  • .NET 9 中 IFormFile 的详细使用讲解
  • Unity肢体控制(关节控制)
  • Ubuntu 20.04配置ollama并下载安装调用本地大语言模型
  • HarmonyOS SDK下的实践与探索
  • 暴雨信息推出电力大模型一体机
  • 在ubuntu上安装ubuntu22.04并ros2 humble版本的docker容器记录
  • LED显示屏驱动电源:恒流与恒压,谁更胜一筹?
  • 在uboot中添加自定义命令
  • Robot Operating System——带有时间戳和坐标系信息的多边形信息
  • ubuntu内网穿透后在公网使用ssh登录
  • could not broadcast input array from shape
  • 盘点那些功能强大的思维导图在线工具,你用过几个
  • 图数据库之TigerGraph
  • R语言 基础笔记 2
  • 【CSS in Depth 2 精译_038】6.2 CSS 定位技术之:绝对定位
  • util-linux 和 dosfstools 开发 ,fdisk mkfs工具移植
  • 【C++ 11多线程加速计算实操教程】
  • New major version of npm available! 8.3.1 -> 10.8.3 报错
  • 分布式环境中,接口超时重试带来的的幂等问题如何解决?
  • Centos7 部署rocketmq
  • 【二等奖论文】2024年华为杯研赛D题成品论文(后续会更新)
  • GNU链接器(LD):输入分区和输出分区介绍
  • MobaXterm基本使用 -- 服务器状态、批量操作、显示/切换中文字体、修复zsh按键失灵
  • 设计原则模式概览
  • 【OpenCV】OpenCV指南:图像处理基础及实例演示
  • 拼多多m 端详情 滑块 分析