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

C++ using:软件设计中的面向对象编程技巧

C++ using:理解头文件与库的使用

  • 引言
  • using声明
    • a. 使用方法和语法
    • b. 实际应用场景举例
      • i. 避免命名冲突
      • ii. 提高代码可读性
    • c. 注意事项和潜在风险
  • using指令
    • a. 使用方法和语法
    • b. 实际应用场景举例
      • i. 将整个命名空间导入当前作用域
      • ii. 代码组织和模块化
  • using枚举
    • a. C++11的新特性
    • b. 使用方法和语法
    • c. 实际应用场景举例
      • i. 引入枚举值,简化代码
      • ii. 提高代码可读性
    • d. 注意事项和潜在风险
  • using类型别名
    • a. 使用方法和语法
    • b. 实际应用场景举例
      • i. 简化复杂类型的定义
      • ii. 提高代码可维护性
    • c. 注意事项和潜在风险
  • using在模板中的应用
    • a. 使用方法和语法
    • b. 实际应用场景举例
      • i. 简化模板元编程
      • ii. 类型推导和类型特性
    • c. 注意事项和潜在风险
  • 使用建议和最佳实践
    • a. 使用using关键字的优缺点分析
    • b. 何时应该使用using声明、指令、枚举和类型别名
    • c. 使用using关键字的最佳实践和规范
  • 总结

引言

C++作为一门具有广泛应用的高级编程语言,自20世纪80年代由Bjarne Stroustrup发明以来,不断地发展和演变。C++在C语言的基础上引入了面向对象编程(OOP)的概念,使得程序员可以编写更为复杂和高效的代码。随着C++98、C++03、C++11、C++14、C++17和C++20等一系列标准的发布,C++不断地引入新特性和优化,以满足不断变化的软件开发需求。

在C++中,命名空间和作用域是两个非常重要的概念。命名空间主要用于组织代码,防止在不同的库或模块中出现命名冲突。C++的命名空间可以嵌套,并且允许在同一个命名空间内声明多个同名实体,但它们必须具有不同的作用域。作用域则定义了程序中变量、函数和对象的可见性和生命周期,控制着程序中不同部分之间的访问权限。

为了简化代码编写和提高代码可读性,C++引入了using关键字。using关键字具有多种用途,包括using声明、using指令、using枚举和using类型别名。通过使用using关键字,程序员可以在不同的作用域中导入命名空间中的实体,避免重复编写冗长的命名空间前缀,同时还可以防止命名冲突。此外,using关键字在模板编程中也发挥着重要作用,可以简化模板元编程,实现类型推导和类型特性等高级功能。

在本文中,我们将详细介绍C++中using关键字的各种用途,语法和实际应用场景,并提供一些最佳实践和使用建议,以帮助程序员编写更为简洁、高效且易于维护的代码。


using声明

a. 使用方法和语法

using声明主要用于将命名空间中的某个特定实体导入到当前作用域,从而避免重复编写命名空间前缀。使用using声明的语法如下:

using namespace_name::entity_name;

在这里,namespace_name表示命名空间的名称,entity_name表示要导入的实体名称,如变量、函数、类等。通过using声明,我们可以直接使用实体名称,而不需要加上命名空间前缀。

b. 实际应用场景举例

i. 避免命名冲突

假设我们有两个不同的命名空间,分别包含了相同名称的函数,但它们的实现是不同的。通过使用using声明,我们可以在当前作用域中导入这两个函数,而不会引起命名冲突:

namespace A {void func() {// 实现A版本的func}
}namespace B {void func() {// 实现B版本的func}
}void main() {using A::func; // 导入A命名空间的funcusing B::func; // 导入B命名空间的funcA::func(); // 调用A命名空间的funcB::func(); // 调用B命名空间的func
}

ii. 提高代码可读性

在某些情况下,命名空间的名称可能非常长,导致代码变得冗长和难以阅读。通过使用using声明,我们可以简化代码并提高可读性:

#include <iostream>namespace very_long_namespace_name {void print_hello() {std::cout << "Hello, World!" << std::endl;}
}int main() {using very_long_namespace_name::print_hello;print_hello(); // 简化代码,提高可读性return 0;
}

c. 注意事项和潜在风险

虽然using指令可以简化代码并提高可读性,但在使用时也需要注意一些潜在的风险:

  • 命名冲突。由于using指令将整个命名空间导入到当前作用域,因此可能导致命名冲突。在使用using指令时,请确保导入的命名空间中的实体名称与当前作用域中的实体名称不冲突。
  • 不要滥用using指令。使用using指令会增加代码的隐式依赖,可能导致代码难以理解和维护。适当使用using声明可能是一个更好的选择,因为它只导入所需的实体。
  • 避免在头文件中使用using指令。在头文件中使用using指令可能导致不必要的命名冲突,因为头文件可能被多个源文件包含。在头文件中,推荐使用using枚举和using类型别名:

using指令

a. 使用方法和语法

using指令的作用是将整个命名空间导入到当前作用域,这样我们可以直接使用命名空间中的所有实体而无需为它们添加命名空间前缀。使用using指令的语法如下:

using namespace namespace_name;

在这里,namespace_name表示要导入的命名空间的名称。

b. 实际应用场景举例

i. 将整个命名空间导入当前作用域

在某些情况下,我们可能需要频繁地使用某个命名空间中的多个实体。通过使用using指令,我们可以将整个命名空间导入当前作用域,以简化代码:

#include <iostream>
#include <vector>
#include <string>using namespace std;int main() {vector<string> names = {"Alice", "Bob", "Charlie"};for (const auto& name : names) {cout << name << endl;}return 0;
}

在这个例子中,我们使用了std命名空间中的多个实体(如vector、string和cout等)。通过使用using namespace std;,我们可以直接使用这些实体而无需为它们添加std::前缀。

ii. 代码组织和模块化

在大型项目中,使用命名空间可以帮助我们更好地组织代码。通过使用using指令,我们可以在需要的地方将整个命名空间导入当前作用域,以便更方便地使用其中的实体:

// file: my_library.h
namespace my_library {class MyClass {// ...};void my_function() {// ...}
}// file: main.cpp
#include "my_library.h"using namespace my_library;int main() {MyClass obj;my_function();return 0;
}

using枚举

a. C++11的新特性

自C++11起,我们可以使用using枚举来将枚举类型中的枚举值直接导入到当前作用域。这使得我们可以在不加枚举类型名称前缀的情况下直接访问枚举值,从而简化代码和提高可读性。

b. 使用方法和语法

使用using枚举的语法如下:

using enum enum_name;

在这里,enum_name表示要导入的枚举类型的名称。

c. 实际应用场景举例

i. 引入枚举值,简化代码

假设我们有一个名为Colors的枚举类型,其中包含了一些颜色的枚举值。通过使用using枚举,我们可以直接访问这些枚举值:

enum class Colors {RED,GREEN,BLUE
};void print_color(Colors color) {using enum Colors;switch (color) {case RED:std::cout << "Red" << std::endl;break;case GREEN:std::cout << "Green" << std::endl;break;case BLUE:std::cout << "Blue" << std::endl;break;}
}int main() {using enum Colors;print_color(RED); // 输出 "Red"return 0;
}

ii. 提高代码可读性

在某些情况下,枚举类型的名称可能较长,导致代码变得冗长和难以阅读。通过使用using枚举,我们可以简化代码并提高可读性。

d. 注意事项和潜在风险

使用using枚举时,应注意避免命名冲突。如果当前作用域中已经存在与枚举值同名的实体,使用using枚举可能导致命名冲突。在这种情况下,建议使用完整的枚举类型名称和枚举值来消除歧义。

using类型别名

a. 使用方法和语法

using类型别名可以为复杂的类型定义简洁易懂的别名。使用using类型别名的语法如下:

using alias_name = original_type;

在这里,alias_name表示新定义的类型别名,original_type表示原始类型。

b. 实际应用场景举例

i. 简化复杂类型的定义

在某些情况下,类型定义可能非常复杂,导致代码难以阅读。通过使用using类型别名,我们可以为这些复杂类型定义简洁的别名:

#include <map>
#include <string>using StringIntMap = std::map<std::string, int>;int main() {StringIntMap my_map;my_map["one"] = 1;my_map["two"] = 2;my_map["three"] = 3;for (const auto& pair : my_map) {std::cout << pair.first << " : " << pair.second << std::endl;
}return 0;
}

在这个例子中,我们使用using类型别名将std::map<std::string,int>定义为StringIntMap,从而简化了代码并提高了可读性。

ii. 提高代码可维护性

使用using类型别名可以使代码更易于维护。如果需要更改原始类型,只需更改类型别名的定义,而无需在整个代码库中进行搜索和替换。这样可以大大减少错误和遗漏的风险。

c. 注意事项和潜在风险

使用using类型别名时,应注意以下几点:

    1. 为类型别名选择有意义的名称。使用简洁且易懂的名称可以提高代码的可读性。
    1. 避免过度使用类型别名。虽然类型别名可以简化代码,但过度使用可能导致代码结构混乱。在合适的场景下使用类型别名,以保持代码清晰和易于理解。
    1. 在适当的作用域中定义类型别名。为了避免命名冲突和全局污染,建议在需要使用类型别名的作用域中定义它们。

using在模板中的应用

a. 使用方法和语法

在C++模板编程中,using关键字可以用于定义模板类型别名和模板嵌套类型。使用using关键字定义模板类型别名的语法如下:

template<typename T>
using alias_name = some_template<T>;

在这里,alias_name表示模板类型别名,some_template表示原始模板类型,T表示模板参数。

b. 实际应用场景举例

i. 简化模板元编程

在模板元编程中,using关键字可以用于简化复杂的模板表达式。例如,使用std::conditional模板来根据条件选择类型:

#include <type_traits>template<bool B, typename T, typename F>
using conditional_t = typename std::conditional<B, T, F>::type;template<typename T>
using add_pointer_t = typename std::add_pointer<T>::type;template<typename T>
struct MyTemplate {using type = conditional_t<std::is_integral<T>::value, add_pointer_t<T>, T>;
};int main() {MyTemplate<int>::type x; // x的类型为int*MyTemplate<double>::type y; // y的类型为double
}

ii. 类型推导和类型特性

使用using关键字可以帮助我们更容易地进行类型推导和操作类型特性。例如,我们可以使用std::enable_if来实现SFINAE(Substitution Failure Is Not An Error)技术:

#include <iostream>
#include <type_traits>template<typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
void foo(const T& value) {std::cout << "Integral type: " << value << std::endl;
}template<typename T, typename = std::enable_if_t<!std::is_integral<T>::value>>
void foo(const T& value) {std::cout << "Non-integral type: " << value << std::endl;
}int main() {foo(42); // 输出 "Integral type: 42"foo(3.14); // 输出 "Non-integral type: 3.14"
}

c. 注意事项和潜在风险

在模板编程中使用using关键字时,也需要注意一些潜在的风险:

  • 在模板中正确使用using关键字。请确保在模板中正确地使用using关键字,遵循模板类型别名和嵌套类型的语法规则。
  • 避免过度复杂化。尽管using关键字可以简化模板元编程,但过于复杂的模板表达式可能导致代码难以理解和维护。在合适的场景下使用using关键字,并保持代码清晰和易于理解。
  • 注意编译时错误。模板编程可能导致复杂的编译时错误。当使用using关键字时,请确保编译时错误能够被合理地处理,并给出有意义的错误信息。

使用建议和最佳实践

a. 使用using关键字的优缺点分析

优点:

  • 提高代码可读性:using关键字可以简化代码,使得代码更加简洁和易读。
  • 避免命名冲突:通过使用命名空间和using声明,可以减少命名冲突的风险。
    提高代码可维护性:使用using类型别名可以使代码更易于维护,减少因修改类型而引入的错误。

缺点:

  • 命名冲突:使用using指令时,可能导致命名冲突,特别是在全局作用域内。
  • 隐式依赖:使用using关键字可能导致代码之间的隐式依赖,使代码难以理解和维护。

b. 何时应该使用using声明、指令、枚举和类型别名

  • 使用using声明:在需要导入特定命名空间中的一个或几个实体时,使用using声明是一个不错的选择。这样可以避免整个命名空间的导入,减少命名冲突的风险。
  • 使用using指令:在需要频繁使用某个命名空间中的实体时,可以考虑使用using指令。但需要注意避免命名冲突,特别是在包含头文件的情况下。
  • 使用using枚举:当需要将枚举类型的枚举值直接导入到当前作用域以简化代码和提高可读性时,可以使用using枚举。
  • 使用using类型别名:为复杂类型定义简洁易懂的别名,以提高代码可读性和可维护性。

c. 使用using关键字的最佳实践和规范

  • 避免在全局作用域中使用using指令:在全局作用域中使用using指令可能导致命名冲突和全局污染。建议在局部作用域或函数内部使用using指令。

  • 在头文件中谨慎使用using关键字:避免在头文件中使用using指令,因为它可能导致不必要的命名冲突。在头文件中,推荐使用using声明或完全限定的名称。

  • 使用有意义的类型别名:为类型别名选择简洁且具有描述性的名称,以提高代码的可读性和可维护性。

  • 保持代码清晰和易于理解:在使用using关键字时,应注意保持代码清晰和易于理解。避免使用过于复杂的模板表达式,以防止代码变得难以阅读和维护。

  • 遵循项目规范和编码标准:在使用using关键字时,应遵循项目规范和编码标准。这将有助于保持代码一致性,使团队成员更容易理解和维护代码。

  • 使用using类型别名替换typedef:在C++11及更高版本中,建议使用using类型别名替换typedef,因为using类型别名更具可读性,且可以处理模板类型别名。

  • 限制using声明的使用范围:只有在确实需要时才使用using声明。避免在不必要的地方引入实体,这将有助于减少命名冲突的风险。

  • 谨慎使用using枚举:在使用using枚举时,注意避免命名冲突。如果当前作用域中已经存在与枚举值同名的实体,使用using枚举可能导致命名冲突。在这种情况下,建议使用完整的枚举类型名称和枚举值来消除歧义。


总之,C++中的using关键字具有多种用途,如using声明、using指令、using枚举和using类型别名。
遵循最佳实践和规范,可以充分利用using关键字的优势,编写简洁、高效且易于维护的代码。
在使用过程中,务必注意潜在的风险,如命名冲突、隐式依赖等,从而确保代码质量。

总结

C++中的using关键字具有多种用途,如using声明、using指令、using枚举和using类型别名。
在不同的应用场景中,using关键字可以简化代码、提高代码可读性、避免命名冲突以及提高代码可维护性。
然而,在使用using关键字时,也需要注意潜在的风险,如命名冲突、滥用using声明或指令等。
通过遵循最佳实践和使用建议,程序员可以充分利用using关键字的优势,编写更为简洁、高效且易于维护的代码。

相关文章:

C++ using:软件设计中的面向对象编程技巧

C using:理解头文件与库的使用引言using声明a. 使用方法和语法b. 实际应用场景举例i. 避免命名冲突ii. 提高代码可读性c. 注意事项和潜在风险using指令a. 使用方法和语法b. 实际应用场景举例i. 将整个命名空间导入当前作用域ii. 代码组织和模块化using枚举a. C11的新特性b. 使用…...

修建灌木顺子日期

题目 有 N 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晩会修剪一棵灌 木, 让灌木的高度变为 0 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始, 每天向右修剪一棵灌木。当修剪了最右侧的灌木后, 她会调转方向, 下一天开 始向左修剪灌木。直到修剪了最左的灌木后再次调转方…...

深入学习JavaScript系列(七)——Promise async/await generator

本篇属于本系列第七篇 第一篇&#xff1a;#深入学习JavaScript系列&#xff08;一&#xff09;—— ES6中的JS执行上下文 第二篇&#xff1a;# 深入学习JavaScript系列&#xff08;二&#xff09;——作用域和作用域链 第三篇&#xff1a;# 深入学习JavaScript系列&#xff…...

Mybatis中的Map的使用和模糊查询的需求实现及其防SQL注入优化

文章目录一.Map的使用和模糊查询的需求实现及其防SQL注入优化1.1 Map的使用1.2 模糊查询的实现1.2.1 防SQL注入优化1.2.2 总结一.Map的使用和模糊查询的需求实现及其防SQL注入优化 1.1 Map的使用 替换之前的根据ID查询信息&#xff1a; 1.编写接口&#xff1a; User getUse…...

【redis】redis缓存更新策略

目录一、缓存更新策略二、主动更新策略三、Cache Aside Pattern3.1 删除缓存还是更新缓存?3.2 如何保证缓存与数据库的操作同时成功或失败&#xff1f;3.3 先操作缓存还是先操作数据库3.3.1 先删缓存再删库3.3.2 先删库再删缓存一、缓存更新策略 1.内存淘汰&#xff1a;不用自…...

LeetCode刷题--复制带随机指针的链表

复制带随机指针的链表1.题目2.解题思路3.完整代码1.题目 题目链接: https://leetcode.cn/problems/copy-list-with-random-pointer/ 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 …...

关于我的第一台电脑 华硕

2011年买的&#xff0c;第一台电脑是华硕 U36KI243SD 13.3英寸 白色 i5 1G独显 USB3.0 500G 当时花了5699&#xff0c;着实是一笔巨款&#xff0c;我同学看了一眼就说“我C&#xff0c;这本真好”。 买它主要还是因为好看。当时win7也才开始流行&#xff0c;感觉用上这个本&…...

【华为OD机试 2023最新 】 最大化控制资源成本(C++ 100%)

文章目录 题目描述输入描述输出描述备注用例题目解析C++题目描述 公司创新实验室正在研究如何最小化资源成本,最大化资源利用率,请你设计算法帮他们解决一个任务混部问题: 有taskNum项任务,每个任务有开始时间(startTime),结束时间(endTime),并行度(parallelism)…...

leetcode 有序数组的平方(977)

题目 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 示例 1&#xff1a; 输入&#xff1a;nums [-4,-1,0,3,10] 输出&#xff1a;[0,1,9,16,100] 解释&#xff1a;平方后&#xff0c;数组变…...

文本三剑客之awk

文本三剑客之awkawk命令的简要处理流程awk命令的执行过程NR输出分割符和输入分割符案例awk命令引用shell变量awk的几个内置函数流控数组awk命令的简要处理流程 awk命令的执行过程 awk BEGIN{commands} pattern{commands} END{commands}files 执行BEGIN {commands}语句块中的语…...

RK3568平台开发系列讲解(驱动基础篇)IS_ERR函数的使用

🚀返回专栏总目录 文章目录 一、IS_ERR函数二、内核错误码沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 IS_ERR 函数的使用。 一、IS_ERR函数 对于任何一个指针来说,必然存在三种情况: 一种是合法指针一种是 NULL (也就是空指针)一种是错误指针(也就…...

特殊的类之注解

注解&#x1f699;注解的入门和作用以及原理示例注解的方法名就是属性名Retention的作用Target的作用注解的属性设置默认值天生我材必有用&#xff0c;千金散尽还复来。——唐代李白《将进酒》 在Java中&#xff0c;注解实际上是特殊类型的接口&#xff0c;当我们使用注解时&am…...

商业分享:盲盒电商开启电商新可能

盲盒&#xff0c;顾名思义&#xff0c;一个看不出里面装着什么东西的盒子。当你看不见盲盒里的商品时&#xff0c;你会思考盲盒里可能装着什么&#xff0c;它会诱发你的好奇心&#xff0c;而在好奇心的促使下&#xff0c;你会不由自主地买一个拆开来看&#xff0c;刚好大多数盲…...

【计算机架构】如何计算 CPU 时间

目录 0x00 响应时间和吞吐量&#xff08;Response Time and Throughput&#xff09; 0x01 相对性能&#xff08;Relative Performance&#xff09; 0x02 执行时间测量&#xff08;Measuring Execution Time&#xff09; 0x03 CPU 时钟&#xff08;Clocking&#xff09; 0x…...

银行数字化转型导师坚鹏:银行行长如何进行数字化转型

银行行长如何进行数字化转型 ——数字化转型背景下重塑银行行长核心竞争力 授课背景&#xff1a; 很多银行存在以下问题&#xff1a;银行行长不知道如何进行数字化转型&#xff1f;银行行长不清楚银行数字化能力模型的内涵&#xff1f;银行行长不知道如何通过数字化转型提…...

N32G45x学习笔记--- gpio引脚复用

关于gpio的引脚复用需要开启复用时钟 RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);官方引脚复用: 芯片上电默认使能 SWD-JTAG 调试接口,调试接口被映射到 GPIO 端口上 禁止 JTAG 使能SWJ-DP /* 禁止 JTAG 使能SWJ-DP */GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_S…...

ArcGIS Pro中使用深度学习的高分辨率土地覆盖制图

本文非常详细的讲解了利用深度学习在高分辨率土地覆盖制图的应用&#xff0c;本文作者&#xff1a;Amin Tayyebi&#xff0c;文章从数据准备到训练U-Net模型等等细节都有讲解。本译文只是使用谷歌翻译而成。文章可能有错误语句及不通顺情况&#xff0c;所以仅供参考学习。有需要…...

【学习笔记】「NOI2018」冒泡排序

从题解的角度来说&#xff0c;这是一道简单题。不过考场上在没有任何人提示的情况下要想出正确的结论其实并不容易。 我自己做这道题的时候&#xff0c;因为没有想清楚题目给出的下界能取到的充要条件是什么&#xff0c;所以到了很晚才猜到结论&#xff0c;以至于难以为继。 …...

【Ruby学习笔记】3.Ruby 语法及数据类型

前言 本章介绍Ruby的语法和数据类型。 Ruby 语法 让我们编写一个简单的 Ruby 程序。所有的 Ruby 文件扩展名都是 .rb。所以&#xff0c;把下面的源代码放在 test.rb 文件中。 实例 #!/usr/bin/ruby -wputs "Hello, Ruby!";在这里&#xff0c;假设您的 /usr/bin …...

华为OD机试题【字符匹配】用 Java 解 | 含解题说明

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典本篇题目:字符匹配 题目 给你一个字符串…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

如何在看板中有效管理突发紧急任务

在看板中有效管理突发紧急任务需要&#xff1a;设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP&#xff08;Work-in-Progress&#xff09;弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中&#xff0c;设立专门的紧急任务通道尤为重要&#xff0c;这能…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...