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

【android 蓝牙开发——蓝牙耳机】

【android 蓝牙开发——传统蓝牙】

【android 蓝牙开发——BLE(低功耗)蓝牙 2021-10-09更新】

总结一下蓝牙开发的基本使用以及蓝牙耳机的断开和链接。

所以需权限:

  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Android12 的蓝牙权限 如果您的应用与已配对的蓝牙设备通信或者获取当前手机蓝牙是否打开 --><uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android12 的蓝牙权限 如果您的应用查找蓝牙设备(如蓝牙低功耗 (BLE) 外围设备) --><uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- Android12 的蓝牙权限 如果您的应用使当前设备可被其他蓝牙设备检测到 --><uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

注意这里需要位置权限。

开启权限:

 ActivityResultLauncher<Intent> bluetoothOpenLaunch;private void startBluetooth() {bluetoothOpenLaunch = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {@Overridepublic void onActivityResult(ActivityResult result) {System.out.println("MainActivity.onActivityResult" + result.getResultCode());if (Activity.RESULT_OK == result.getResultCode()) {getPermission();}}});Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {ArrayList<String> arrayListOf = new ArrayList<>();arrayListOf.add(Manifest.permission.BLUETOOTH_CONNECT);PermissionUtils.permission(String.valueOf(arrayListOf)).callback(new PermissionUtils.SimpleCallback() {@Overridepublic void onGranted() {System.out.println("MainActivity.onGranted");bluetoothOpenLaunch.launch(intent);}@Overridepublic void onDenied() {System.out.println("MainActivity.onDenied");ToastUtils.showLong("请开启蓝牙权限");}}).request();} else {bluetoothOpenLaunch.launch(intent);}}private void getPermission() {ArrayList<String> arrayListOf = new ArrayList<>();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {arrayListOf.add(Manifest.permission.BLUETOOTH_SCAN);arrayListOf.add(Manifest.permission.BLUETOOTH_CONNECT);arrayListOf.add(Manifest.permission.BLUETOOTH_ADVERTISE);}arrayListOf.add(Manifest.permission.BLUETOOTH);arrayListOf.add(Manifest.permission.BLUETOOTH_ADMIN);arrayListOf.add(Manifest.permission.ACCESS_FINE_LOCATION);arrayListOf.add(Manifest.permission.ACCESS_COARSE_LOCATION);PermissionUtils.permission(String.valueOf(arrayListOf)).callback(new PermissionUtils.SimpleCallback() {@Overridepublic void onGranted() {ToastUtils.showLong("蓝牙相关权限已成功授权");BluetoothManager blueManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);//mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()mBluetoothAdapter = blueManager.getAdapter();}@Overridepublic void onDenied() {ToastUtils.showLong("请开启蓝牙权限");}}).request();}

监听蓝牙连接配对等相关广播,建议直接采用以下方式:(也有其他方法,搜索低功耗蓝牙的方式 startLeScan )

 //注册BoradcasrReceiverprivate void registerReceiver() {IntentFilter discoveryFilter = new IntentFilter();discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);discoveryFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);discoveryFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);discoveryFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);discoveryFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);discoveryFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);discoveryFilter.addAction(BluetoothDevice.ACTION_FOUND);registerReceiver(discoveryReceiver, discoveryFilter);}//蓝牙搜索广播的接收器@SuppressLint("MissingPermission")private BroadcastReceiver discoveryReceiver = new BroadcastReceiver() {String pin = "0000";  //此处为你要连接的蓝牙设备的初始密钥,一般为 1234 或 0000@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  //获取设备,发现远程蓝牙设备if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {Log.i(TAG, "onReceive: 开始搜索");} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {Log.i(TAG, "onReceive:  搜索结束");} else if (BluetoothDevice.ACTION_FOUND.equals(action)) {// //获取扫描到的设备String name = bluetoothDevice.getName();String address = bluetoothDevice.getAddress();Log.i(TAG, "onReceive: name=" + name + " address=" + address);/*if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) {Log.i(TAG, "已配对 onReceive: name=" + name + " address=" + address);} else {}*///已经配对boolean isExist = false;for (DeviceBean device : bluetoothDevices) {if (device.getAddress().equals(address)) {isExist = true;}}if (!isExist) {bluetoothDevices.add(new DeviceBean(name, address));mAdapter.notifyDataSetChanged();}} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {//Log.i(TAG, "onReceive:  绑定状态改变");int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);Log.i(TAG, "onReceive:  绑定状态改变 state=" + state);if (state == 12) {Log.i(TAG, "onReceive:  绑定成功 ");ToastUtils.showLong("绑定成功");String name = bluetoothDevice.getName();String address = bluetoothDevice.getAddress();boolean isExist = false;for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {isExist = true;}}if (!isExist) {/*for (DeviceBean device : pairedDevices) {device.setStatus(false);}*/DeviceBean deviceBean = new DeviceBean(name, address);deviceBean.setStatus(true);pairedDevices.add(0, deviceBean);mDevicePairedAdapter.notifyDataSetChanged();} else {for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {device.setStatus(true);mDevicePairedAdapter.notifyDataSetChanged();break;}}}}} else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {//Log.i(TAG, "onReceive:  连接状态改变");int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.ERROR);String name = bluetoothDevice.getName();String address = bluetoothDevice.getAddress();Log.i(TAG, "onReceive:  连接状态改变 state=" + state);switch (state) {case 0://断开成功for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {device.setStatus(false);mDevicePairedAdapter.notifyDataSetChanged();break;}}break;//case 1: break;case 2://连接成功Log.i(TAG, "onReceive:  连接成功 address=" + address);ToastUtils.showLong("连接成功");for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(address)) {device.setStatus(true);mDevicePairedAdapter.notifyDataSetChanged();break;}}break;default:break;}} else if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(action)) {Log.i(TAG, "onReceive:  配对");try {// bluetoothDevice.setPairingConfirmation(true);// abortBroadcast();// bluetoothDevice.setPin(pin.getBytes());//1:/*  ClsUtils.setPairingConfirmation(bluetoothDevice.getClass(),bluetoothDevice,true);//2:如果没有将广播终止,则会出现一个一闪而过的配对框。abortBroadcast();//3.调用setPin方法进行配对..boolean ret = ClsUtils.setPin(bluetoothDevice.getClass(), bluetoothDevice, pin);System.out.println("ConnectingDevicesActivity.onReceive ret="+ret);*/} catch (Exception e) {throw new RuntimeException(e);}} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {Log.i(TAG, "onReceive:   蓝牙开关状态改变");int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);switch (state) {case BluetoothAdapter.STATE_OFF:break;case BluetoothAdapter.STATE_ON:break;}} else {Log.i(TAG, "onReceive:   else action=" + action);}}};

我们也可以获取已配对蓝牙列表:

private void initData() {Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();if (bondedDevices != null && bondedDevices.size() > 0) {for (BluetoothDevice bondedDevice : bondedDevices) {System.out.println("ConnectingDevicesActivity.initData name==" + bondedDevice.getName());DeviceBean deviceBean = new DeviceBean(bondedDevice.getName(), bondedDevice.getAddress());pairedDevices.add(deviceBean);}mDevicePairedAdapter.notifyDataSetChanged();}}

蓝牙耳机断开和连接的具体方法:

  public boolean isDisconnected = false;/*** 断开蓝牙设备连接** @param bluetoothDevice BluetoothDevice*/public void disconnect(BluetoothDevice bluetoothDevice) {currentBluetoothDevice = bluetoothDevice;//获取A2DP代理对象mBluetoothAdapter.getProfileProxy(this, disconnectProfileServiceListener, BluetoothProfile.HEADSET);//获取HEADSET代理对象mBluetoothAdapter.getProfileProxy(this, disconnectProfileServiceListener, BluetoothProfile.A2DP);}private final BluetoothProfile.ServiceListener disconnectProfileServiceListener = new BluetoothProfile.ServiceListener() {@Overridepublic void onServiceDisconnected(int profile) {System.out.println("ConnectingDevicesActivity.onServiceDisconnected profile="+profile);}@Overridepublic void onServiceConnected(int profile, BluetoothProfile proxy) {try {if (profile == BluetoothProfile.HEADSET) {//使用HEADSET的协议断开蓝牙设备(使用了反射技术调用断开的方法)BluetoothHeadset bluetoothHeadset = (BluetoothHeadset) proxy;boolean isDisConnect = false;try {Method connect = null;if (isDisconnected) {connect = bluetoothHeadset.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class); //disconnect connect} else {connect = bluetoothHeadset.getClass().getDeclaredMethod("connect", BluetoothDevice.class); //disconnect connect}connect.setAccessible(true);isDisConnect = (boolean) connect.invoke(bluetoothHeadset, currentBluetoothDevice);if (isDisconnected) {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "断开通话成功" : "断开通话失败") + currentBluetoothDevice.getName());} else {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "链接通话成功" : "链接通话失败") + currentBluetoothDevice.getName());}} catch (Exception e) {e.printStackTrace();}}if (profile == BluetoothProfile.A2DP) {//使用A2DP的协议断开蓝牙设备(使用了反射技术调用断开的方法)BluetoothA2dp bluetoothA2dp = (BluetoothA2dp) proxy;boolean isDisConnect = false;try {Method connect = null;if (isDisconnected) {connect = bluetoothA2dp.getClass().getDeclaredMethod("disconnect", BluetoothDevice.class);} else {connect = bluetoothA2dp.getClass().getDeclaredMethod("connect", BluetoothDevice.class);}connect.setAccessible(true);isDisConnect = (boolean) connect.invoke(bluetoothA2dp, currentBluetoothDevice);if (isDisconnected) {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "断开音频成功" : "断开音频失败") + currentBluetoothDevice.getName());} else {Log.d(TAG, "isDisConnect:" + (isDisConnect ? "链接音频成功" : "链接音频失败") + currentBluetoothDevice.getName());}} catch (Exception e) {e.printStackTrace();}if (isDisConnect) {for (DeviceBean device : pairedDevices) {if (device.getAddress().equals(currentBluetoothDevice.getAddress())) {device.setStatus(!isDisconnected);mDevicePairedAdapter.notifyDataSetChanged();break;}}}}} catch (Exception e) {e.printStackTrace();}}};

源码

相关文章:

【android 蓝牙开发——蓝牙耳机】

【android 蓝牙开发——传统蓝牙】 【android 蓝牙开发——BLE&#xff08;低功耗&#xff09;蓝牙 2021-10-09更新】 总结一下蓝牙开发的基本使用以及蓝牙耳机的断开和链接。 所以需权限&#xff1a; <uses-permission android:name"android.permission.ACCESS_FIN…...

Golang goroutine 进程、线程、并发、并行

goroutine 看一个需求 需求&#xff1a;要求统计1-200000000000的数字中&#xff0c;哪些是素数? 分析思路&#xff1a; 1)传统的方法&#xff0c;就是使用一个循环&#xff0c;循环的判断各个数是不是素数&#xff08;一个任务就分配给一个cpu去做&#xff0c;这样很不划算…...

如何做到安全上网

随着信息化的发展&#xff0c;企业日常办公越来越依赖互联网&#xff0c;而访问互联网过程中&#xff0c;会遇到各种各样不容忽视的风险&#xff0c;例如员工主动故意的数据泄漏&#xff0c;后台应用程序偷偷向外部发信息&#xff0c;木马间谍软件的外联&#xff0c;以及各种挖…...

优维低代码实践:菜单

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…...

git merge 如何撤销

如果只是 git merge 未进行其他 git 操作&#xff0c;可以使用 git merge --abort 撤销如果 git merge 之后&#xff0c;再 git add&#xff0c;可以使用 git reset HEAD 或 git reset HEAD file (前者多个文件&#xff0c;后者单个文件)如果 git merge 之后&#xff0c;再 git…...

解读package.json 中的功能

使用 npm init 比较全 一步一步的走,用于完成 package.json 中的各个声明 npm init -y 生成简易的模板下面解读下 package.json 中的功能"version": "1.0.0", //版本号1. 主版本号&#xff1a;非常大的改动 vue2 和 vue3 的改变 2. 功能的升级&#xff0c;…...

UMA 2 - Unity Multipurpose Avatar☀️四.UMA人物部位的默认颜色和自定义(共享)颜色

文章目录 🟥 人物颜色介绍1️⃣ 使用默认颜色2️⃣ 使用自定义颜色🟧 UMA自定义颜色的作用🟨 自定义颜色还可作为共享颜色🟥 人物颜色介绍 UMA不同部位的颜色分为默认的内置颜色和我们新定义的颜色. 1️⃣ 使用默认颜色 比如不勾选UseSharedColor时,使用的眼睛的默认…...

phpstorm配置php运行环境

1&#xff0c;首先安装phpstrom&#xff0c;按照提示的步骤一步一步来就行 2&#xff0c;新建一个项目然后在里面找到这个位置 3&#xff0c;找到php所在的位置&#xff0c;找不到就直接在搜索框中搜索 4&#xff0c;这里要配置php的运行环境&#xff0c;一定要记得自己安装软…...

算法训练营day49|动态规划 part10:(LeetCode 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II)

121. 买卖股票的最佳时机 题目链接&#x1f525; 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大…...

Swagger 使用教程

Swagger 官网&#xff1a; API Documentation & Design Tools for Teams | Swagger 整合swagger 依赖&#xff1a; springfox-swagger2 springfox-swagger-ui <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</a…...

单例模式-饿汉模式、懒汉模式

单例模式&#xff0c;是设计模式的一种。 在计算机这个圈子中&#xff0c;大佬们针对一些典型的场景&#xff0c;给出了一些典型的解决方案。 目录 单例模式 饿汉模式 懒汉模式 线程安全 单例模式 单例模式又可以理解为是单个实例&#xff08;对象&#xff09; 在有些场…...

UG\NX二次开发 复制3元素的double数组到另一个数组 UF_VEC3_copy

文章作者:里海 来源网站:王牌飞行员_里海_里海NX二次开发3000例,里海BlockUI专栏,C\C++-CSDN博客 简介: UG\NX二次开发 复制3元素的double数组到另一个数组 UF_VEC3_copy。仔细看第二段代码 。 效果: 代码: #include "me.hpp"void ufusr(char* param, …...

骨传导耳机对人体有危险吗?会损害听力吗?

如果在使用骨传导耳机的时候控制好时间和音量&#xff0c;是不会对人体带来危险和造成伤害的。 下面跟大家解释一下为什么骨传导耳机对人体没有危害&#xff0c;最大的原因就是骨传导耳机不需要空气传导&#xff0c;而是通过颅骨传到听觉中枢&#xff0c;传输过程中几乎没有噪…...

Spring Boot @Value读不到Nacos配置中心的值。(properties配置文件)

读不到配置中心的值&#xff0c; 配置中心的配置文件名字&#xff08;Data ID的值&#xff09;要以.properties结尾。 如果是yaml&#xff0c;就以yaml命名。...

Rocky Linux怎么安装mysql

Rocky Linux怎么安装mysql 在Rocky Linux上安装MySQL可以通过以下步骤实现&#xff1a; 更新软件包列表 ⭐️⭐️⭐️必要的&#xff0c;必须更新&#xff0c;更新会顺利很多&#xff01;&#xff01;&#xff01;⭐️⭐️⭐️ 在安装MySQL之前&#xff0c;建议先更新软件包…...

轻量级软件FastGithub实现稳定访问github

当我们想访问全球最大的“同性交友网站”https://github.com/ 时&#xff0c;总会出现无法访问的界面&#xff0c;令人非常苦恼&#xff1a;幸运的是&#xff0c;有一种轻量级的软件可以帮助我们稳定地访问GitHub&#xff0c;那就是FastGithub。 什么是FastGithub&#xff1f…...

芯科蓝牙BG27开发笔记6-精简第一个程序

1. 这些IO的控制代码在哪里&#xff1f; 还是蓝牙点灯程序&#xff1a; 首先需要对pinout做一些精简&#xff1a; 为了简化工程&#xff0c;去掉了不必要的IO。 至于PTI接口是什么&#xff0c;怎么用&#xff0c;不知道&#xff0c;现在不考虑&#xff1a; 但是提出以下问题…...

Android8.1 hal 加载wifi ko模块流程

Android如果发现wifi没有正常启动&#xff0c;从下面两个方面 1.是否正常编译出wifi ko文件&#xff0c;如果没有&#xff0c;说明编译的有问题&#xff0c;ko文件的地址vendor/lib/module/devices/wifi 2.如果有编译出ko文件&#xff0c;但还提示Wifi HAL start failed之类的…...

Unity SteamVR 开发教程:SteamVR Input 输入系统(2.x 以上版本)

文章目录 &#x1f4d5;前言&#x1f4d5;教程说明&#x1f4d5;导入 SteamVR 插件&#x1f4d5;SteamVR Input 窗口⭐action.json 文件⭐窗口面板⭐SteamVR_Input 目录 &#x1f4d5;SteamVR 动作的类型⭐Boolean⭐Single⭐Vector2⭐Vector3⭐Pose⭐Skeleton⭐Vibration &…...

PyTorch中,卷积层、池化层、转置卷积层输出特征图形状计算公式总结

在PyTorch中&#xff0c;卷积层&#xff08;Convolutional Layer&#xff09;、池化层&#xff08;Pooling Layer&#xff0c;例如最大池化层&#xff09;、以及转置卷积层&#xff08;Transpose Convolutional Layer&#xff0c;也称为反卷积层或上采样层&#xff09;的输出特…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...