条件编译代码记录

#include <iostream>// 基类模板
template<typename T>
class Base {
public:void func() {std::cout << "Base function" << std::endl;}
};// 特化的子类
template<typename T>
class Derived : public Base<T> {
public:void func() {std::cout << "Derived function" << std::endl;}
};// 完全特化的子类
template<>
class Derived<int> : public Base<int> {
public:void func() {std::cout << "Specialized Derived<int> function" << std::endl;}
};int main() {Derived<double> d1;  // 这个对象使用的是 Derived<double>d1.func();           // 输出: "Derived function"Derived<int> d2;     // 这个对象使用的是完全特化的 Derived<int>d2.func();           // 输出: "Specialized Derived<int> function"Base<double> b;      // 基类实例b.func();            // 输出: "Base function"return 0;
}

std::enable_if_t<std::is_same_v<U, Dim3>, Ptr> 如何使用?

#include <iostream>
#include <type_traits>// 定义不同的MyType子类型
class MyTypeA {
public:void process() {std::cout << "Processing MyTypeA" << std::endl;}
};class MyTypeB {
public:void process() {std::cout << "Processing MyTypeB" << std::endl;}
};class MyTypeC {
public:void process() {std::cout << "Processing MyTypeC" << std::endl;}
};// 函数模板,用于处理MyTypeA
template <typename T>
typename std::enable_if_t<std::is_same_v<T, MyTypeA>, void> process(T& obj) {obj.process(); // 处理MyTypeA
}// 函数模板,用于处理MyTypeB
template <typename T>
typename std::enable_if_t<std::is_same_v<T, MyTypeB>, void> process(T& obj) {obj.process(); // 处理MyTypeB
}// 函数模板,用于处理MyTypeC
template <typename T>
typename std::enable_if_t<std::is_same_v<T, MyTypeC>, void> process(T& obj) {obj.process(); // 处理MyTypeC
}template <typename U>
void templateFunction(U& obj) {process(obj); // 调用具体的process函数
}int main() {MyTypeA myObjA;MyTypeB myObjB;MyTypeC myObjC;templateFunction(myObjA);  // 输出: Processing MyTypeAtemplateFunction(myObjB);  // 输出: Processing MyTypeBtemplateFunction(myObjC);  // 输出: Processing MyTypeC// 如果你尝试以下代码,将导致编译错误:// std::string str; // 这里是一个不支持的类型// templateFunction(str); // 编译错误,因为没有对应的process函数处理std::string
}

if constexpr (std::is_same_v< >和std::enable_if_t<std::is_same_v>有什么区别 

template<typename T, typename U>;

std::enable_if_t<std::is_same_v<U, Dim3>, void> 代码里可以对T和U多条件判断吗?

对模板参数 T 和 U 进行多条件判断。在 C++ 中,可以通过使用 std::enable_ifconstexpr 表达式以及组合多种类型特性(比如 std::is_integralstd::is_floating_point 等)来实现复杂的条件逻辑。

以下是几种常见的方法来对 T 和 U 进行多条件判断:

1. 使用 std::enable_if

可以将多个条件组合在一起,例如使用逻辑运算符 && 或 ||。以下是示例代码:

#include <type_traits>template<typename T, typename U>
class Shaper {
public:// 当 T 是整型且 U 是 Dim3 时,启用 reshape 函数template<typename = std::enable_if_t<std::is_integral<T>::value && std::is_same_v<U, Dim3>>>void reshape(float* data, ...) {// 实现}// 另外一个 reshape 函数,当 U 是其他类型时(例如,浮点型)template<typename = std::enable_if_t<std::is_floating_point<U>::value>>void reshape(float* data, ...) {// 实现其他逻辑}
};

2. 通过类型萃取和其他类型特性进行组合

您可以还可以使用组合类型特性进行更复杂的判断:

#include <type_traits>template<typename T, typename U>
class Shaper {
public:// 当 T 是整型且 U 是 Dim3 或者 U 是某个其他类型时启用 reshape 函数template<typename = std::enable_if_t<std::is_integral<T>::value && (std::is_same_v<U, Dim3> || std::is_floating_point<U>::value)>>void reshape(float* data, ...) {// 实现}
};

3. 组合多个 enable_if 条件

您也可以在模板上直接组合多个 enable_if 条件:

#include <type_traits>template<typename T, typename U>
class Shaper {
public:template<typename = std::enable_if_t<std::is_integral<T>::value && std::is_same_v<U, Dim3> && SomeOtherCondition<U>::value>>void reshape(float* data, ...) {// 实现}
};

has_value_member


// 模板函数,只有在T没有value成员时才会启用
template<typename T>
typename std::enable_if<!has_value_member<T>::value>::type

#include <iostream>
#include <type_traits>// 用于检测类型T是否有一个名为 value_type 的类型成员
template <typename T, typename = void>
struct has_value_type : std::false_type {};// 特化 if 提供实现
template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {};// 一个示例结构体,具备 value_type
struct StructWithValue {using value_type = int; // 定义类型成员value_type value; // 实例成员
};// 一个不具备 value_type 的结构体
struct StructWithoutValue {double value; // 没有定义类型成员value_type
};template<typename T, typename Enable = void>
class Widget;// 特化 Widget,当T有value_type时
template<typename T>
class Widget<T, typename std::enable_if<has_value_type<T>::value>::type> {
public:void printIfHasValue() {std::cout << "T has value type member." << std::endl;}
};// 特化 Widget,当T没有value_type时
template<typename T>
class Widget<T, typename std::enable_if<!has_value_type<T>::value>::type> {
public:void print() {std::cout << "This type doesn't have a value_type member." << std::endl;}
};int main() {Widget<StructWithValue> wa;wa.printIfHasValue(); // 正确: T是有值类型成员的结构体Widget<StructWithoutValue> wb;wb.print(); // 输出: This type doesn't have a value_type member.return 0;
}

多模版参数处理

template <typename T, typename U,bool DeviceType>,有时需要template <typename T, typename U, typename D,bool DeviceType>,怎么设计呢?

1特化:

#include <iostream>
#include <type_traits>// 主模板,使用 std::conditional 选取 D 类型
template <typename T, typename U, bool DeviceType, typename D = void>
class MyTemplate;// 特化,处理只有两个类型和布尔值的情况
template <typename T, typename U, bool DeviceType>
class MyTemplate<T, U, DeviceType, void> {
public:void print() {std::cout << "Using template with two types (T, U) and a bool." << std::endl;}
};// 特化,处理带有第三个类型 D 的情况
template <typename T, typename U, typename D, bool DeviceType>
class MyTemplate<T, U, DeviceType, D> {
public:void print() {std::cout << "Using template with two types (T, U), an additional type (D), and a bool." << std::endl;}
};int main() {MyTemplate<int, double, true> instance1;  // 使用两个类型的模板instance1.print();MyTemplate<int, double, true, char> instance2;  // 使用三个类型的模板instance2.print();return 0;
}

特化二:

#include <iostream>
#include <type_traits>// 基本模板,两个类型和一个布尔值
template <typename T, typename U, typename D = void, bool DeviceType = false>
class MyTemplate {
public:void print() {std::cout << "Using template with T, U, D (defaulted), and DeviceType." << std::endl;}
};// 特化版本,当 D 不是 void 时
template <typename T, typename U, typename D>
class MyTemplate<T, U, D, true> {
public:void print() {std::cout << "Using template with T, U, and a third type D, with DeviceType set to true." << std::endl;}
};int main() {MyTemplate<int, double> myInstance1; // 使用默认的D为void,DeviceType为falsemyInstance1.print();MyTemplate<int, double, char, true> myInstance2; // 指定了D和DeviceTypemyInstance2.print();return 0;
}

 

当您希望根据条件选择不同数量的模板参数时,一种常见的方法是使用递归模板或辅助结构如类型特征来处理这种情况。然而,对于您提出的特定需求(即有条件地在模板中使用额外的类型参数),一种实际的方法是使用模板偏特化和默认模板参数联合使用,但不能通过改变参数数量的方式来实现。

下面我们将使用默认模板参数和SFINAE(Substitution Failure Is Not An Error)技巧来提供一个解决方案。

方案说明

一个更实用的方法是设计一个包裹类型或使用一个已经存在的如 std::enable_ifstd::conditional 或自定义类型特征来根据条件启用或禁用第三个类型参数。但对于直接添加或移除模板参数,在C++模板中这是不可能实现的。取而代之的是,我们可以按需使用第三个类型参数,让它在某些情况下为 void 类型或其他不影响的类型。

改进后的例子

考虑到上述限制,如果我们要实现一个这样的结构,我们必须以稍微不同的方式思考。以下是一种使用 std::conditional 来选择第三个参数是一个有效类型还是 void 的方法。此方法并不完美,但展示了如何基于给定的布尔值 DeviceType 来静态选择类型。

#include <iostream>
#include <type_traits>template <typename T, typename U, bool DeviceType, typename D = void>
class MyTemplate {
public:using ConditionallyEnabledType = typename std::conditional<DeviceType, D, void>::type;void print() {if constexpr (std::is_same<ConditionallyEnabledType, void>::value) {std::cout << "Template with T, U, and DeviceType, D is void." << std::endl;} else {std::cout << "Template with T, U, DeviceType and D as an additional type." << std::endl;}}
};int main() {MyTemplate<int, double, false> myInstance1; // D will be considered voidmyInstance1.print();MyTemplate<int, double, true, char> myInstance2; // D will be enabled as 'char'myInstance2.print();return 0;
}

 

为什么不完美?

你的代码使用了模板的SFINAE(Substitution Failure Is Not An Error)技术,来根据编译时的条件(是否指定了类型参数D)来选择性地启用某个类型。这个设计对于特定模板类的某些条件来说是有效的,但有几个潜在的问题和局限性需要注意:

  1. 模板参数默认值不完整:你的模板参数D默认值是void,这会导致在某些情况下不完全匹配预期行为。如果DeviceTypefalse,你默认没有为D提供任何类型信息,这使得编译器难以解析你的模板,因为它无法确定哪个类型是默认的。虽然你的代码可能能够编译成功,但这种不明确性可能会导致混淆或误解。通常更好的做法是明确指定所有模板参数的类型,即使它们有默认值。

  2. 模板参数不完整:你的模板类依赖于一个布尔值来决定是否启用某个类型,这种设计对于特定的用例可能是有效的,但它限制了模板的灵活性。如果模板设计用于更广泛的用途,可能需要更复杂的逻辑来根据多个条件启用或禁用类型。此外,使用布尔值作为模板参数通常不是一个好的做法,因为它增加了代码与特定编译逻辑的耦合性。更常见的是使用条件模板或别名来达成同样的效果。

针对这些问题,一个改进的方式是重新定义模板以考虑所有的参数依赖和上下文,比如:

template <typename T, typename U> // 无需显式的DeviceType和D类型参数,因为这些可以作为函数内部逻辑的一部分处理
class MyTemplate {
public:template <typename D = void> // 使用默认模板参数来处理可能的额外类型Dvoid print() { // 此函数将根据是否提供了额外的类型D来处理不同的逻辑if constexpr (std::is_void<D>::value) { // 使用std::is_void而不是直接比较来检查类型是否为voidstd::cout << "Template with T and U." << std::endl; // 根据是否提供了额外的类型输出不同的消息} else {std::cout << "Template with T, U, and additional type D." << std::endl;}}
};
```在这个修改中,`DeviceType`是隐藏在逻辑内部而不作为一个独立的模板参数出现的。我们通过将布尔值与`void`进行比较(如检查类型是否为void),或者在编译器基于上下文的情境中创建内部函数而不是完整的独立参数集来解决前面的问题。然而这种方式虽然避免了对非用户直接参与的中间类型的直接引用,但它仍然依赖于特定的编译逻辑来根据条件启用或禁用某些功能。在设计复杂的模板时,需要权衡灵活性和清晰度之间的权衡。

#include <iostream>
#include <type_traits>struct Color {};// 假设 Linear 是某种类型
struct Gray {};// 模板类定义
template <typename T, typename U>
class MyTemplate {
public:template <typename D = Gray> //默认void print() {if constexpr (std::is_same_v<D, Color>) {std::cout << "Template with T and U." << std::endl;}else {std::cout << "Template with T, U, and additional type D." << std::endl;}}
};int main() {// 使用基本模板实例化,T = int, U = floatMyTemplate<int, float> myTemplate1;myTemplate1.print();  // 输出:Template with T, U, and additional type D.// 使用额外的类型D,这里我们指定为LinearmyTemplate1.print<Color>();  // 输出:Template with T and U.// 另一个实例化,使用不同的类型MyTemplate<double, char> myTemplate2;myTemplate2.print();  // 输出:Template with T, U, and additional type D.// 继续使用额外的类型myTemplate2.print<Gray>();  // 输出:Template with T and U.return 0;
}

上面程序只判断一层模版,如果判断多层模版呢?

#include <iostream>
#include <type_traits>struct dim3
{};struct dim2
{};struct Color {};// 假设 Linear 是某种类型
struct Gray {};// 模板类定义
template <typename T, typename U>
class MyTemplate {
public:template <typename D = Gray> //默认void print() {if constexpr (std::is_same_v<D, Color> && std::is_same_v<U, dim3>) {std::cout << "Template with T and U." << std::endl;}else {std::cout << "Template with T, U, and additional type D." << std::endl;}}
};int main() {// 使用基本模板实例化,T = int, U = floatMyTemplate<int, dim3> myTemplate1;myTemplate1.print();  // 输出:Template with T, U, and additional type D.// 使用额外的类型D,这里我们指定为LinearmyTemplate1.print<Color>();  // 输出:Template with T and U.// 另一个实例化,使用不同的类型MyTemplate<double, char> myTemplate2;myTemplate2.print();  // 输出:Template with T, U, and additional type D.// 继续使用额外的类型myTemplate2.print<Gray>();  // 输出:Template with T and U.MyTemplate<double, dim3> myTemplate3;myTemplate3.print<Color>();  // 输出:Template with T, U, and additional type D.return 0;
}

使用变参模板

另一种方式是使用变参模板。这种方法允许更灵活的参数数量和类型。下面的示例展示了如何设计可以接受不同参数数量的模板:

#include <iostream>
#include <type_traits>// 基本模板定义
template <typename T, typename U, bool DeviceType, bool HasExtraType = false, typename... Args>
class MyTemplate;// 特化版本,仅基于两种类型和布尔值
template <typename T, typename U, bool DeviceType>
class MyTemplate<T, U, DeviceType, false> {
public:void print() {std::cout << "Using template with two types and a bool." << std::endl;}
};// 特化版本,带有额外类型参数
template <typename T, typename U, bool DeviceType, typename... Args>
class MyTemplate<T, U, DeviceType, true, Args...> {
public:void print() {std::cout << "Using template with two types, one additional type, and a bool." << std::endl;}
};int main() {MyTemplate<int, double, true> myInstance1;myInstance1.print(); // 将调用第一个特化版本MyTemplate<int, double, true, true, char> myInstance2; // 需要明确指定有额外类型myInstance2.print(); // 将调用第二个特化版本return 0;
}

 

 功能:指定类型才能调用成员函数

  typename std::enable_if<std::is_same<D, Dim2>::value>::type 是 C++ 中一种常用的 SFINAE(Substitution Failure Is Not An Error)技术,主要用于条件性地启用或禁用模板函数。让我们逐步解析这个表达式。

逐步解析

  1. std::is_same<D, Dim2>::value

    • std::is_same 是 C++ 标准库中的一个类型特性,它用于检查两个类型是否相同。
    • std::is_same<D, Dim2>::value 将返回一个布尔值:如果 D 是 Dim2 类型,则为 true;否则为 false
  2. std::enable_if

    • std::enable_if 是一个模板类,它的作用是在满足特定条件时定义类型,同时在不满足条件时不定义类型。
    • std::enable_if<Condition, T>::type 的逻辑是:
      • 如果 Condition 为 true,那么 std::enable_if 将定义一个类型 T
      • 如果 Condition 为 false,则不定义这个类型,并导致 SFINAE(替代失败不是错误)。
  3. typename std::enable_if<std::is_same<D, Dim2>::value>::type

    • 如果 std::is_same<D, Dim2>::value 为 trueenable_if 会定义一个类型,并通过 typename 关键字进行引用。通常,这个类型会被设为 void(默认)。
    • 如果条件不成立(即 D 不是 Dim2),那么这个类型不会被定义,导致这一重载函数在不满足的情况下被排除。

用法示例

在模板函数中使用这个技术的目的是:

  • 条件编译:使得某个特定的函数重载只有在某些情况下可用。
#include <iostream>
#include <type_traits>struct Dim2 {};
struct Dim3 {};class Resizer {
public:// 当 D 为 Dim2 时有效template<typename D>typename std::enable_if<std::is_same<D, Dim2>::value>::typeresize() {std::cout << "Resizing for Dim2!" << std::endl;}// 当 D 为 Dim3 时有效template<typename D>typename std::enable_if<std::is_same<D, Dim3>::value>::typeresize() {std::cout << "Resizing for Dim3!" << std::endl;}
};int main() {Resizer resizer;resizer.resize<Dim2>(); // 输出: Resizing for Dim2!resizer.resize<Dim3>(); // 输出: Resizing for Dim3!// resizer.resize<int>(); // 如果取消注释,这将导致编译错误return 0;
}

总结

      通过 std::enable_if,可以实现特定条件下的函数重载功能。在这个例子中,resize 函数的版本只有在模板参数 D 为 Dim2 或 Dim3 时才是可用的。其他类型(如 int)将导致编译错误,而不会使程序崩溃或其他运行时错误,有效地增强了类型安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/54298.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL数据库——MYSQL管理

MYSQL数据库安装完成后&#xff0c;自带四个数据库&#xff0c;具体作用如下&#xff1a; 常用工具 1.mysql 不是指mysql服务&#xff0c;而是指mysql的客户端工具 例如&#xff1a; 2.mysqladmin 这是一个执行管理操作的客户端程序&#xff0c;可以用它来检查服务器的配置和…

多线程篇六

多线程篇六 如笔者理解有误欢迎交流指正~⭐ 什么是单例模式&#xff1f; 单例模式是最常见的 设计模式. 顾名思义&#xff0c;单例模式指的就是单个实例的模式.&#xff08;针对某些类只能使用一个对象的场景【如MySQL、JDBC、DataSource】&#xff09; 设计模式 设计模式是…

数据结构之二叉树(1)

数据结构之二叉树&#xff08;1&#xff09; 一、树 1、树的概念与结构 &#xff08;1&#xff09;树是一种非线性的数据结构&#xff0c;由n(n>0)个有限结点组成一个具有层次关系的集合。 &#xff08;2&#xff09;树有一个特殊的结点&#xff0c;叫做根结点&#xff…

Linux:Bash中的文件描述符

相关阅读 Linuxhttps://blog.csdn.net/weixin_45791458/category_12234591.html?spm1001.2014.3001.5482 Linux中的所有进程&#xff0c;都拥有自己的文件描述符(File Descriptor, FD)&#xff0c;它是操作系统在管理进程和文件时的一种抽象概念。每个文件描述符由一个非负整…

【Mac】系统环境配置

常用工具 Navicat PJ版本&#xff1a;this 提取密码&#xff1a;v31p Host切换器 SwitchHosts termius 一款好用的Linux服务器连接工具&#xff1a; termius 小飞机 dddd&#xff1a;&#x1fa9c; Git mac安装git有好多种方式&#xff0c;自带的xcode或者通过Homebr…

[数据集][目标检测]智慧交通铁路异物入侵检测数据集VOC+YOLO格式802张7类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;802 标注数量(xml文件个数)&#xff1a;802 标注数量(txt文件个数)&#xff1a;802 标注类别…

pytorch快速入门(一)—— 基本工具及平台介绍

前言 该pytorch学习笔记应该配合b站小土堆的《pytorch深度学习快速入门教程》使用 环境配置&#xff1a;Anaconda Python编译器&#xff1a;pycharm、jupyter 两大法宝函数 dir&#xff08;&#xff09;&#xff1a;知道包中有什么东西&#xff08;函数 / 属性..…

C++的封装

手动封装一个顺序表&#xff08;SeqList&#xff09;,分文件编译实现 有私有成员&#xff1a;顺序表数组的起始地址 ptr、 顺序表的总长度&#xff1a;size、顺序表的实际长度&#xff1a;len 成员函数&#xff1a;初始化 init(int n) 判空&#xff1a;empty 判满&#xff1a;f…

【计算机网络 - 基础问题】每日 3 题(一)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

云手机的便捷性和安全性体现在哪?

随着5G技术的迅速发展&#xff0c;云手机在游戏、电商以及新媒体营销等领域中的应用日益广泛。它不仅能够显著降低成本、提升效率&#xff0c;还随着边缘计算和云技术的进步&#xff0c;展现出无限的增长潜力。 云手机的便捷性体现在哪里&#xff1f; 云手机的便捷性毋庸置疑。…

基于ExtendSim的 电子制造 仿真模型

说明&#xff1a; 此模型表示电路板制造设施。该过程有4个步骤&#xff1a; *焊料制备 *组件放置 *烤箱 *检查 详情&#xff1a; *烤箱的容量为10张卡&#xff0c;但如果烤箱循环开始时仅能处理5张卡&#xff0c;则最多只能处理5张。 *如果检查员发现问题&#xff0c;他们将修理…

大数据新视界 --大数据大厂之 Cassandra 分布式数据库:高可用数据存储的新选择

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【matlab】将程序打包为exe文件(matlab r2023a为例)

文章目录 一、安装运行时环境1.1 安装1.2 简介 二、打包三、打包文件为什么很大 一、安装运行时环境 使用 Application Compiler 来将程序打包为exe&#xff0c;相当于你使用C编译器把C语言编译成可执行程序。 在matlab菜单栏–App下面可以看到Application Compiler。 或者在…

数据结构和算法之线性结构

原文出处:数据结构和算法之线性结构 关注码农爱刷题&#xff0c;看更多技术文章&#xff01;&#xff01;&#xff01; 线性结构是一种逻辑结构&#xff0c;是我们编程开发工作应用最广泛的数据结构之一。线性结构是包含n个相同性质数据元素的有限序列。它的基本特征是&…

docker入门安装及使用

docker概述 docker是一种容器技术&#xff0c;它提供了标准的应用镜像&#xff08;包含应用和应用多需要的依赖&#xff09;&#xff0c;因此&#xff0c;我们可以非常轻松的在docker中安装应用&#xff0c;安装好的应用相当于一个独立的容器 如下图所示&#xff0c;为docker中…

如何将Git本地代码推送到Gitee云端仓库

如何将Git本地代码推送到Gitee云端仓库 在使用Git进行版本控制时&#xff0c;将本地代码推送到远程仓库是一个基本且重要的操作。本文将详细介绍如何将你的Git本地代码推送到Gitee&#xff08;码云&#xff09;云端仓库。Gitee是一个国内非常流行的代码托管平台&#xff0c;类…

Redis 执行 Lua,能保证原子性吗?

前言 小张目前在使用分布式锁 Redisson 实现一个需求。那我在想我能否自己手撸一个能用于分布式环境的锁呢&#xff1f;于是果然尝试。 历经一天后&#xff0c;小张手撸的锁终于写出来了&#xff0c;再次给各位看看&#xff0c;看给位有没有什么优化的建议&#xff1a; // 加…

VSCode 定义代码模板

在使用编写代码的过程中&#xff0c;经常会写一些固定代码段。 以 Java 为例&#xff0c;定义实体类时一般都会编写序列化版本号&#xff1a; Serial private static final long serialVersionUID 1L;这段代码是固定写法&#xff0c;基本不会变&#xff0c;如果每次都手写的…

sqlgun靶场漏洞挖掘

1.xss漏洞 搜索框输入以下代码&#xff0c;验证是否存在xss漏洞 <script>alert(1)</script> OK了&#xff0c;存在xss漏洞 2.SQL注入 经过测试&#xff0c;输入框存在SQL注入漏洞 查询数据库名 查询管理员账号密码 此处密码为MD5加密&#xff0c;解码内容如下 找…

使用Python免费将pdf转为docx

刚刚想将pdf转换为docx文档时&#xff0c;居然要收费 还好我学过编程&#xff0c;这不得露两手 将pdf 转换为 docx 文档 的操作步骤 我这里使用的是Python语言 &#xff08;1&#xff09;在终端上安装 pdf2docx 是一个 Python 库&#xff0c;它可以将 PDF 文件转换为 Word (…