第八层:模板(上)

简介: 第八层:模板(上)

前情回顾


在上一层中,我遇到了面向对象的最后一个特性——多态,使用多态可以让代码组织结构更加情绪,使可读性变强,利于程序的前期和后期的扩展和维护,掌握多态之后,面向对象结束了, 后面会是什么呢…


🚄上章地址:第七层:多态


模板


上到了第八层,映入眼帘的是一个巨大的石碑,“你来了,在C++中,除了面向过程编程和面向对象编程以外,还有一种编程思想,叫做泛型编程,泛型编程主要通过模板实现,这层就需要你掌握模板的力量…"。


模板的概念


模板就是建立一个通用的模具,大大提高复用性,比如PPT模板、空白的学生证,这些东西都有一些特点,不能直接使用,需要使用者去添加一些东西,而且不是通用的,比如这个PPT模板是做年度总结的,那就不能强套到一些和年度总结不着边的东西上,因此可以总结出模板的特点。


模板的特点


1.模板只是一个框架

2.这个框架不是万能的


模板分类


在C++中模板分为两类:


函数模板

类模板


函数模板


作用


建立一个通用函数,其函数的返回类型和形参可以不具体制定,用一个虚拟的类型来代表


语法


函数模板的语法为:


templatte< typename T>

函数的声明或者定义

解释:


template:声明创建函数模板

typename:表明其后面的符号是一种通用的数据类型,可以用class替代。

T:通用的数据类型,可以替换成别的字母

可以尝试写一个函数模板:


#include<iostream>
using namespace std;
template<typename T>
void print(T a)
{
  cout << a << endl;
}
int main()
{
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

可以正常跑起来,那函数模板怎么使用呢?


函数模板的使用


1.自动类型推导:直接传入类型,让编译器自己识别是什么类型

2.显示制定类型:告诉编译器是什么类型,语法如下:

函数名< 是什么数据类型 >(参数)

验证一下两种使用方法:


自动类型推导

#include<iostream>
using namespace std;
template<typename T>
void print(T a)
{
  cout << a << endl;
}
void test1()
{
  print(1);
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png

显示指定类型

#include<iostream>
using namespace std;
template<typename T>
void print(T a)
{
  cout << a << endl;
}
void test1()
{
  print<int>(1);
}
int main()
{
  test1();
  return 0;
}

2d65d23f6d4748949b924e4057485923.png

注意事项

1.自动类型推导必须推导出一致的数据类型才可以使用

2.模板必须确定出T的数据类型,才可以使用

第一点解释:


#include<iostream>
using namespace std;
template<typename T>
void print(T a,T b)
{
  cout << a << endl;
}
void test1()
{
  int a = 0;
  char b = 0;
  print(a,b);
}
int main()
{
  test1();
  return 0;
}

2e9b90b2ca334476abebe75bafe6eeaa.png

可以看到,一个int的类型和一个char类型的数据,两个类型就不一致,这个时候,T不知道自己应该是什么,所以报错,说明对于自动类型推导就需要让两个类型一致,那显示指定类型呢?


#include<iostream>
using namespace std;
template<typename T>
void print(T a,T b)
{
  cout << a << b << endl;
}
void test1()
{
  int a = 0;
  char b = 0;
  print<int>(a,b);
}
int main()
{
  test1();
  return 0;
}

4cebaac233b3433da32a72337a77fc60.png

显示指定类型就可以使用。


第二点解释:

当函数模板没有参数的时候,可以直接调用吗?


#include<iostream>
using namespace std;
template<typename T>
void print()
{
  cout << "hello world" << endl;
}
void test1()
{
  print();
}
int main()
{
  test1();
  return 0;
}

6de278e6d6694ce5bb08e7e842b7e74b.png

是不可以直接调用的,因为使用函数模板时,必须人编译器知道通用数据类型是什么,就算没有参数,也需要,这个时候可采用显示指定类型,不管是什么类型,都能跑去来:


#include<iostream>
using namespace std;
template<typename T>
void print()
{
  cout << "hello world" << endl;
}
void test1()
{
  print<int>();
  print<char>();
  print<double>();
}
int main()
{
  test1();
  return 0;
}

7a399525ddec4b77923c464820b33738 (1).png


普通函数和函数模板的区别


普通函数调用可以发生自动类型转换(隐式类型转换)

函数模板在调用时,如果利用自动类型推导,不会发生隐式类型转换

如果利用显示指定类型,可以发生隐式类型转换

普通函数:


#include<iostream>
using namespace std;
int Swap(int a, int b)
{
  return a + b;
}
void test1()
{
  int a = 20;
  char b = '1';
  int c=Swap(a, b);
  cout << c << endl;
}
int main()
{
  test1();
  return 0;
}

7a399525ddec4b77923c464820b33738.png

c是69,这是因为发生了隐式类型转换,char转换成了int,同时这是字符1的ASCII码值为49,49加20,就是69。

函数模板:

自动类型推导在上面的注意事项说到,必须推导出统一的数据类型才能跑起来,所以这个时候传两个类型不同的一定是会报错的,就不进行验证了,这个时候试着用显示指定类型试试:


#include<iostream>
using namespace std;
template<typename T>
int Swap(T a, T b)
{
  return a + b;
}
void test1()
{
  int a = 20;
  char b = '1';
  int c=Swap<int>(a, b);
  cout << c << endl;
}
int main()
{
  test1();
  return 0;
}


0a2653c851af460fa595bd959398a8f1.png

0a2653c851af460fa595bd959398a8f1.png

这个时候,编译器会将参数内的所有数视为int类型的,就发生了隐式类型转换。


普通函数和函数模板的调用规则


1.如果函数模板和普通函数都可以实现时,优先调用普通函数

2.可以通过空模板参数来强调函数模板,让使用函数模板

3.函数模板可以发生重载

4。如果函数模板可以产生更好的匹配,就使用函数模板


优先调用普通函数


#include<iostream>
using namespace std;
template<typename T>
int Add(T a, T b)
{
  cout << "函数模板调用" << endl;
  return a + b;
}
int Add(int a, int b)
{
  cout << "普通函数调用" << endl;
  return a + b;
}
void test1()
{
  int a = 20;
  int b = 20;
  int c=Add(a, b);
  cout << c << endl;
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png

可以发现两个函数实现内容相同,但是优先调用的普通函数。


空模板强调函数模板


空模板的语法:函数名<>(传参)

#include<iostream>
using namespace std;
template<typename T>
int Add(T a, T b)
{
  cout << "函数模板调用" << endl;
  return a + b;
}
int Add(int a, int b)
{
  cout << "普通函数调用" << endl;
  return a + b;
}
void test1()
{
  int a = 20;
  int b= 20;
  int c=Add<>(a, b);
  cout << c << endl;
}
int main()
{
  test1();
  return 0;
}

2d65d23f6d4748949b924e4057485923.png

这个时候就调用了函数模板了,就是空模板起的作用,可以强制调用模板。


函数模板可以发生重载


#include<iostream>
using namespace std;
template<typename T>
int Add(T a, T b)
{
  return a + b;
}
template<typename T>
int Add(T a, T b, T c)
{
  return a + b + c;
}
void test1()
{
  int a = 20;
  int b= 20;
  int c = 20;
  int d = Add<>(a, b, c);
  cout << d << endl;
}
int main()
{
  test1();
  return 0;
}


2e9b90b2ca334476abebe75bafe6eeaa.png

2e9b90b2ca334476abebe75bafe6eeaa.png

相关文章
|
3天前
|
数据采集 人工智能 安全
|
13天前
|
云安全 监控 安全
|
4天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
1085 152
|
18天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1751 9
|
9天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
694 152
|
11天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
660 14
|
6天前
|
SQL 自然语言处理 调度
Agent Skills 的一次工程实践
**本文采用 Agent Skills 实现整体智能体**,开发框架采用 AgentScope,模型使用 **qwen3-max**。Agent Skills 是 Anthropic 新推出的一种有别于mcp server的一种开发方式,用于为 AI **引入可共享的专业技能**。经验封装到**可发现、可复用的能力单元**中,每个技能以文件夹形式存在,包含特定任务的指导性说明(SKILL.md 文件)、脚本代码和资源等 。大模型可以根据需要动态加载这些技能,从而扩展自身的功能。目前不少国内外的一些框架也开始支持此种的开发方式,详细介绍如下。
438 5