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

抖音里做我女朋友网站网站开发的时间流程

抖音里做我女朋友网站,网站开发的时间流程,流程优化的七个步骤,被黑网站文章目录 一. 泛型编程二. 函数模板函数模板的原理函数模板的实例化隐式实例化: 让编译器根据实参推演模板参数的实际类型显示实例化: 在函数名后的<>中制定模板参数的世纪类型 模板参数的匹配原则 三. 类模板类模板的定义格式类模板的实例化 一. 泛型编程 如何实现一个…

文章目录

  • 一. 泛型编程
  • 二. 函数模板
    • 函数模板的原理
    • 函数模板的实例化
      • 隐式实例化: 让编译器根据实参推演模板参数的实际类型
      • 显示实例化: 在函数名后的<>中制定模板参数的世纪类型
    • 模板参数的匹配原则
  • 三. 类模板
    • 类模板的定义格式
    • 类模板的实例化

一. 泛型编程

如何实现一个通用的交换函数呢? 参数是不同类型的数据.

void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}

使用函数重载虽然可以实现, 但是仍然有不足:

  1. 重载的函数仅仅是类型不同, 代码复用率比较低, 只要有新类型出现时, 就需要用户自己增加对应的函数
  2. 代码的可维护性比较低, 一个出错可能所有的重载均出错.

如果需要能在用户提供的类型上使用此函数, 这种策略就失效了.


那么, 能否告诉编译器一个模子, 让编译器根据不同的类型利用该模子来生成代码呢?

就像活字印刷术一样, 只要提供了字模, 就可以用不同的颜色来印出同样的字

在这里插入图片描述

C++提供了模板的语法, 给这个"模具"中填充不同的类型, 就可以生成具体类型的代码

泛型编程: 编写与类型无关的通用代码, 是代码复用的一种手段. 模板是泛型编程的基础.

在这里插入图片描述

二. 函数模板

针对上面 Swap 函数有多种类型参数的情况, 可以定义一个通用的函数模板(function template), 而不是为每个类型都定义一个新函数.

一个函数模板就是一个公式, 可用来生成针对特定类型的函数版本. Swap 的模板版本可能像下面这样:

template <typename T>     // 模板定义格式:  template<typename T1, typename T2, ... , typename Tn>
void Swap(T &left, T &right)
{T temp = left;left = right;right = temp;
}

模板定义以关键字 template 开始, 后面跟一个模板参数列表, 这是一个用逗号分割的一个或多个模板参数的列表, 用小于号 < 和 大于号 > 包围起来.

在模板定义中, 模板参数列表不能为空.

模板参数列表的作用很像函数参数列表.
函数参数列表定义了形参对象, 模板参数列表定义了类型.

模板参数表示类或函数定义中用到的类型或值. 当使用模板的时候, 显示或隐式地制定模板实参, 将其绑定到模板参数上.

比如上述的 Swap 函数声明了两个名为 T 的类型参数, T 表示一个类型, T 的实际类型则在编译时根据传入的参数确定.

对于不同的参数类型, 最终调用的函数参数类型也不同

在这里插入图片描述


函数模板的原理

函数模板是一个蓝图, 它本身并不是函数, 是编译器用使用方式产生特定具体类型函数的模具. 所以其实模板就是将本来应该我们做得重复的事情交给了编译器.

在这里插入图片描述

在编译器编译阶段, 对于函数模板的使用, 编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用.

例如: 当用 double 类型使用函数模板时, 编译器通过对实参类型的推演, 将 T 确定为 double 类型, 然后产生一份专门处理 double 类型的代码

注意 函数模板的模板参数类型可以写 typename, 也可以写 class (不可以写 struct).

函数模板的实例化

用不同类型的参数使用函数模板时, 称为函数模板的实例化.

在这里插入图片描述

隐式实例化: 让编译器根据实参推演模板参数的实际类型

template <typename T>
T Add(const T &left, const T &right)
{return left + right;
}int main()
{int a1 = 10, b1 = 20;Add(a1, b1);    // 推演出模板参数类型为 intdouble a2 = 1.1, b2 = 2.2;Add(a2, b2);    // 推演出模板参数类型为 doubleAdd(a1, b2);    // 推演失败return 0;
}

前两个可以通过编译, 函数模板类型相同, 编译器可以推演出函数模板的类型.

第三个传入了一个 int 类型和一个 double 类型, 编译器推演模板参数类型失败.

在这里插入图片描述

因为定义模板函数的时候, 规定了模板函数参数只有一个类型 T, 传入两个类型, 编译器不能确定应该是将 T 演绎成哪个类型.

在模板中, 编译器不会进行类型转换操作, 一旦转换出问题, 编译器就会背黑锅, 所以不会隐式转换.

有两种处理方式:

  1. 用户自己进行强化类型转换
  2. 使用显示实例化
Add(a1, (int)b2);   // 用户自己强制类型转换

显示实例化: 在函数名后的<>中制定模板参数的世纪类型

int main()
{int a1 = 10;double b = 20.0;Add<int> (a1, b2);  // 显示实例化return 0;
}

如果类型不匹配, 编译器会进行隐式类型转换, 如果无法转换成功, 编译器会报错.


如果函数参数没有模板参数, 那么就无法使用隐式实例化, 只能进行显示实例化.

// 申请一个T类型十个元素的数组并返回
template <typename T>
T *f()
{T *p = new T[10];return p;
}int main()
{int *p1 = f<int>();double *p2 = f<double>();return 0;
}

模板参数的匹配原则

  1. 一个非模板函数和一个同名的函数模板同时存在, 而且该函数模板可以被实例化为这个非模板函数
// 专门处理 int 类型的加法函数
int Add(const int &left, const int &right)
{cout << "(int) Add" << endl;return left + right;
}// 通用加法函数
template <typename T>
T Add(const T &left, const T &right)
{cout << "(template) Add" << endl;return left + right;
}int main()
{Add(1, 2);          // 有现成的优先用现成的Add<int>(1, 2);     // 如果指定显示实例化, 用函数模板
}

在这里插入图片描述


  1. 对于非模板函数和同名函数, 如果其他条件都相同, 在调用时会优先调用非模板函数而不会从该模板产生一个实例. 如果模板可以产生一个具有更好匹配的函数, 那么将选择模板.
// 专门处理 int 类型的加法函数
int Add(const int &left, const int &right)
{cout << "(int) Add" << endl;return left + right;
}// 通用加法函数
template <typename T1, typename T2>
T1 Add(const T1 &left, const T2 &right)
{cout << "(template) Add" << endl;return left + right;
}int main()
{Add(1, 2);          // 与非函数模板完全匹配, 不需要函数模板实例化Add(1, 2.0);        // 有更合适的不会进行隐式类型转换调用非函数模板, 而会直接调用函数模板实例化的实例
}

在这里插入图片描述


  1. 函数模板不允许自动类型转换, 而普通函数可以进行自动类型转换
// 专门处理 int 类型的加法函数
int Add(const int &left, const int &right)
{cout << "(int) Add" << endl;return left + right;
}// 通用加法函数
template <typename T>
T Add(const T &left, const T &right)
{cout << "(template) Add" << endl;return left + right;
}int main()
{Add(1, 2.0); // 函数模板不能进行自动类型转换, 只能调用普通函数, 传参的时候进行自动类型转化
}

在这里插入图片描述


总结

  1. 优先调用现有的普通函数
  2. 没有函数模板, 普通函数参数可以自动类型转换的, 使用普通函数.
  3. 可以通过函数模板实例化更合适的函数, 哪怕普通函数可以自动类型转换, 也用函数模板.

三. 类模板

以前写数据结构的时候, 通常会用 typedef 重命名数据结构内数据的类型.
例如 Stack 中用 typedef int STDataType, 制定 Stack 中的数据类型是 int 类型的.

但是, 这样只能保证一次只能用 int, 如果需要用到 double 的, 需要再重新写一份.

有了类模板就能很好的解决这个问题.

类模板的定义格式

template <class T1, class T2,...,class T3>
class 类模板名
{// 类内成员定义
};

例如: Stack

template <class T>
class Stack
{
public:Stack(size_t capacity = 10): _array(new T[capacity]), _capacity(capacity), _top(0){}~Stack();void push(const T &data);//...
private:T *_array;int _capacity;int _top;
};// 类外定义成员函数必须要加模板参数列表
template <class T>
Stack<T>::~Stack()
{delete[](_array);_capacity = _top = 0;
}

类外定义成员函数, 必须要加上模板参数列表声明, 并且指定类域时必须加上模板参数列表.

同时, 类模板成员函数的声明与定义必须放在同一个文件中, 否则编译器会链接失败.

类模板的实例化

类模板实例化与函数模板实例化不同, 类模板都是显示实例化, 需要在类模板名字后面跟<>, 然后将实例化的类型放在<>中即可, 类模板名字不是真正的类, 而实例化的结果才是真正的类

Stack<int> s1;
Stack<double> s2;

普通类的类名即是类型, 而类模板的类名不是类型, 类名<数据类型> 才是整个类的类型.

Stack<int>Stack<double> 不是同一个类, 他们只是同一类模板显示实例化生成的不同类.

本章完.

http://www.yayakq.cn/news/490980/

相关文章:

  • 多语言企业网站模板天翼云官网首页
  • 黄石城乡建设网站营销师
  • 评网网站建设wordpress写入到磁盘
  • wordpress app下载失败宁阳县网络seo
  • 从化网站建设wordpress 评论显示图片
  • 北京电商网站开发公司哪家好网站301重定向 权重转移
  • 东莞人才网站wordpress创建xml
  • 中国建设银行网站运营模式企业网站展示
  • 关于互联网的网站吴中区做网站的公司
  • 品牌网站建设小蝌蚪正能量网站大全
  • 无锡网站制作哪家值得信赖机关网站建设存在的问题
  • 优秀网站页面设计图片制作外贸网站的公司
  • 网站建设阶段it外包项目都在哪接的
  • 济宁网站建设价格在线制作横幅
  • rio门户网站的制作泰安集团网站建设报价
  • 网站简繁转换济宁创企网络技术有限公司
  • 网站外包价格上海 房地产网站建设
  • 阿里云服务器 做网站营业执照咋做网等网站
  • 西宁做网站君博解决网页界面设计包括哪些
  • 傻瓜式网站建设软件建设工程造价管理总站网站
  • 咔咔做受视频网站临夏城乡建设局网站
  • 做网站麻烦吗国内免费一年云服务器
  • 私人定制哪个网站做的比较好最近比较火的关键词
  • 新手网站建设教程专业手机网站建设多少钱
  • 咸阳网站推广北京环球影城可以带水果吗
  • 上门做网站哪里有php做网站毕设答辩问什么
  • 工信部 网站 备案北京网站建设公司 蓝纤科技 网络服务
  • 做网站月薪资多少钱纪检监察网站建设情况汇报
  • 网站上传服务器教程网站绝对路径
  • wap建站程序免费下载大学校园门户网站建设方案