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

C++之模版进阶篇

目录

前言

1.非类型模版参数

2.模版的特化

2.1概念

2.2函数模版特化

2.3 类模板特化

2.3.1 全特化和偏特化

2.3.2类模版特化应用实例

3.模版分离编译

3.1 什么是分离编译

3.2 模板的分离编译

3.3 解决方法

4. 模板总结

结束语


前言

在模版初阶我们学习了函数模版和类模版的相关知识,对模版有了一定的了解,接下来我们将对模版进行进一步的了解,话不多说,直接上货!!!

本节内容

1. 非类型模板参数
2. 类模板的特化
3. 模板的分离编译

1.非类型模版参数

模板参数分类类型形参与非类型形参
类型形参即:出现在模板参数列表中,跟在class或者typename之类的参数类型名称
非类型形参,就是 用一个常量作为类(函数)模板的一个参数 ,在类 ( 函数 ) 模板中可将该参数当成常量来使用

比如我们简单写一个静态栈,可以定义不同大小的栈,这里我们没有传默认参数,传也可以。

template<size_t N>
class Stack {
private:int _a[N];int _top;
};
int main() {Stack<5>s1;Stack<10>s2;return 0;
}
其实非类型形参在大小定义方面用的比较多,把大小当做常量。对于传参都传的是整数。
注意:
1. 浮点数、类对象以及字符串是不允许作为非类型模板参数的
2. 非类型的模板参数必须在编译期就能确认结果
在C++11版本的array用了 非类型的模板参数, 来代替静态数组。
#include <array>
#include <iostream>
using namespace std;
int main(){array<int, 10> a1;array<int, 100> a2;
int a3[10];
return 0;
}

那么用array定义数组的好处是什么呢,是数组初始化吗,当然不是。

相比较于int a3[10],其实array的好处是越界检查方面,array对于数组的读和写都会进行越界检查,而int a3[10],对于读不会检查,而写会检查,进行的是抽取,一般会在数组后面默认分配两个数据大小空间左右。

 array<int, 10> a1;array<int, 100> a2;
// a1[100] = 3;int a3[10];cout << a3[100] << endl;a3[10] = 1;
// a3[12] = 1;

array底层访问是调用了一个函数进行实现,都会调用assert语句来判断。

template<class T, size_t N = 10>
class array
{
public:T& operator[](size_t index) { assert(index < N);return _array[index];}
private:T _array[N];size_t _size;
};

其实对于数组的定义,在C++中我们采用vector来定义,可以进行初始化

vector<int>v(10,1);

但是如果要频繁的开设数组,其实array的效率可能要高些,因为array是在栈上开空间的,栈是向下生长的,vector是在堆上。 

2.模版的特化

2.1概念

通常情况下, 使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结 ,需要特殊处理,比如:实现一个专门用来小于比较的函数模版
class Date {
public:Date(int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day){}bool operator<(const Date& other) const {if (_year != other._year) return _year < other._year;if (_month != other._month) return _month < other._month;return _day < other._day;}/*friend ostream&operator<<(ostream& out, const Date& d) {out << d._year << "-" << d._month << "-" << d._day;return out;}*/
private:int _year;int _month;int _day;
};
template <class T>
bool Less(const T &left,const T& right) {return left < right;
}
int main() {cout << Less(1, 2) << endl; // 可以比较,结果正确Date d1(2024, 7, 9);Date d2(2024, 7, 8);cout << Less(d1, d2) << endl; // 可以比较,结果正确Date* p1 = &d1;Date* p2 = &d2;cout << Less(p1, p2) << endl; // 可以比较,结果错误return 0;
}

 

可以看到, Less 绝对多数情况下都可以正常比较,但是在特殊场景下就得到错误的结果。上述示例中, p1 指向的d1 显然大于 p2 指向的 d2 对象,但是 Less内部并没有比较p1p2指向的对象内容,而比较的是p1p2 指针的地址,这就无法达到预期而错误。
此时,就 需要对模板进行特化。即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式 。模板特化中分为函数模板特化 类模板特化

2.2函数模版特化

函数模板的特化步骤:
1. 必须要先有一个基础的函数模板
2. 关键字template后面接一对空的尖括号<>
3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
4. 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
template <class T>
bool Less(const T &left,const T& right) {return left < right;
}template<>
bool Less<Date*>(Date* const& left, Date* const& right)
{return *left < *right;
}
/*
template<>
bool Less<const Date*>(const Date* const& left, const Date* const& right)
{return *left < *right;
}
*/

注意:const要放在*之后,修饰的才是引用变量本身,放在*之前是修饰指向内容

非const特化

template <class T>
bool Less( T &left,T& right) {return left < right;
}template<>
bool Less<Date*>(Date* &left, Date* &right)
{return *left < *right;
}

所以对于下面这段代码

Date * p1 = & d1 ;
Date * p2 = & d2 ;
cout << Less ( p1 , p2 ) << endl ; // 调用特化之后的版本,而不走模板生成了
注意:一般情况下如果函数模板遇到不能处理或者处理有误的类型,为了实现简单通常都是将该函数直接给 出。
bool Less(Date* left, Date* right)
{return *left < *right;
}
该种实现简单明了,代码的可读性高,容易书写,因为对于一些参数类型复杂的函数模板,特化时特别给出,因此函数模板不建议特化。

2.3 类模板特化

2.3.1 全特化和偏特化

全特化即是将模板参数列表中所有的参数都确定化。
偏特化:任何针对模版参数进一步进行条件限制设计的特化版本。
template<class T1, class T2>
class Data
{
public:Data() { cout << "Data<T1, T2>" << endl; }
private:T1 _d1;T2 _d2;
};
//全特化
template<>
class Data<int, char>
{
public:Data() { cout << "Data<int, char>" << endl; }
private:int _d1;char _d2;
};
//偏特化
template<class T1>
class Data<T1, int> {
public:Data() { cout << "Data<T1, int>" << endl; }
private:T1 _d1;int _d2;
};int main() {Data<int, int>d1;Data<int, char>d2;Data<int, int> d3;return 0;
}

偏特化有以下两种表现方式:

部分特化

将模板参数类表中的一部分参数特化。
 
// 将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:Data() {cout<<"Data<T1, int>" <<endl;}
private:T1 _d1;int _d2;
};
参数更进一步的限制
偏特化并不仅仅是指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本
/两个参数偏特化指针类型
//template<class T1,class T2>
template<typename T1, typename T2>
class Data<T1*, T2*>
{
public:Data()  { cout << "Data<T1*, T2*>" << endl;  }
private:T1 _d1;T2 _d2;
};
//两个参数特化引用类型template<class T1, class T2>class Data<T1&, T2&>{public:Data()  {  cout << "Data<T1&, T2&>" << endl; }private:T1 _d1;T2 _d2;};//一个指针一个引用template<class T1, class T2>class Data<T1&, T2*>{public:Data() { cout << "Data<T1&, T2*>" << endl; }private:T1 _d1;T2 _d2;};

2.3.2类模版特化应用实例

实例1:

class Date {
public:Date(int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}friend ostream&operator<<(ostream& out, const Date& d) {out << d._year << "-" << d._month << "-" << d._day;return out;}
private:int _year;int _month;int _day;
};
/*
template <class T>
bool Less(const T &left,const T& right) {return left < right;
}
*/
template<class T>
struct Less
{bool operator()(const T& x, const T& y) const{return x < y;}
};
int main() {vector<Date>d1;d1.push_back(Date(2024, 8, 25));d1.push_back(Date(2024, 8, 24));d1.push_back(Date(2024, 8, 27));sort(d1.begin(), d1.end(), Less<Date>());for (const auto& date : d1) {cout << date << endl;}return 0;
}

 实例2:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class Date {
public:Date(int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}friend ostream&operator<<(ostream& out, const Date& d) {out << d._year << "-" << d._month << "-" << d._day;return out;}private:int _year;int _month;int _day;
};
template<class T>
class Less
{
public:bool operator()(const T& x, const T& y) const{return x < y;}
};
// 对Less类模板按照指针方式特化/*
template <class T>
bool Less(const T &left,const T& right) {return left < right;
}
*/int main()
{Date d1(2022, 7, 7);Date d2(2022, 7, 6);Date d3(2022, 7, 8);vector<Date> v1;v1.push_back(d1);v1.push_back(d2);v1.push_back(d3);// 可以直接排序,结果是日期升序sort(v1.begin(), v1.end(), Less<Date>());for (const auto& date : v1) {cout << date << endl;}vector<Date*> v2;v2.push_back(&d1);v2.push_back(&d2);v2.push_back(&d3);// 可以直接排序,结果错误日期还不是升序,而v2中放的地址是升序// 此处需要在排序过程中,让sort比较v2中存放地址指向的日期对象// 但是走Less模板,sort在排序时实际比较的是v2中指针的地址,因此无法达到预期sort(v2.begin(), v2.end(), Less<Date*>());for (const auto& date : v2) {cout << *date << endl;}return 0;
}

通过观察上述程序的结果发现,对于日期对象可以直接排序,并且结果是正确的。但是如果待排序元素是指针,结果就不一定正确。因为:sort 最终按照 Less 模板中方式比较,所以只会比较指针,而不是比较指针指向空间中内容,此时可以使用类版本特化来处理上述问题:
// 对Less类模板按照指针方式特化
template<>
struct Less<Date*>
{bool operator()(Date* x, Date* y) const{return *x < *y;}
};

 

3.模版分离编译

3.1 什么是分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

3.2 模板的分离编译

假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义。
// a.h
template<class T>
T Add(const T& left, const T& right);
// a.cpp
template<class T>
T Add(const T& left, const T& right)
{return left + right;
}
// main.cpp
#include"a.h"
int main()
{Add(1, 2);Add(1.0, 2.0);return 0;
}

C/C++程序的运行过程通常包括以下几个步骤:
1. 预处理(Preprocessing):
   - 预处理器处理源代码文件中的预处理指令,如 `#include`、`#define`、`#if`、`#ifdef` 等。
   - 预处理器将包含的文件内容插入到源文件中,处理宏定义,条件编译指令等。
   - 结果是一个扩展的源代码文件,通常以 `.i` 文件(C语言)或 `.ii` 文件(C++语言)表示。
2. 编译(Compilation):
   - 编译器将预处理后的源代码翻译成汇编语言。
   - 在这个阶段,编译器进行词法分析、语法分析、语义分析、中间代码生成和优化等操作。
   - 生成的汇编语言文件通常以 `.s` 文件表示。
3. 汇编(Assembly):
   - 汇编器将汇编语言转换成机器语言指令,这些指令是二进制形式的,可以被计算机的CPU直接执行。
   - 生成的目标代码文件通常以 `.o`(Linux/Unix系统)或 `.obj`(Windows系统)表示。
4. 链接(Linking):
   - 链接器将一个或多个目标文件以及所需的库文件合并成一个可执行文件。
   - 在这个阶段,链接器解析外部引用和符号,合并相同的函数和数据,进行重定位等操作。
   - 最终生成的可执行文件通常以 `.exe`(Windows系统)或无扩展名(Linux/Unix系统)表示。
5. 加载(Loading):
   - 当程序运行时,操作系统负责将可执行文件加载到内存中。
   - 加载器读取可执行文件,并将程序代码和数据映射到内存的适当位置。
6. 执行(Execution):
   - CPU开始执行程序的主函数,程序正式开始运行。
   - 在执行过程中,程序可能会进行各种计算、输入输出操作、调用库函数等。
7. 终止(Termination):
   - 程序执行完成后,或者遇到无法处理的错误时,程序会终止。
   - 在终止前,程序可能需要执行一些清理工作,如关闭打开的文件、释放分配的内存等。
 

链接之前各文件没有交互,模版没有实例化没有生成指令,代码,链接就出现问题。

3.3 解决方法

1. 将声明和定义放到一个文件 "xxx.hpp" 里面或者 xxx.h 其实也是可以的 推荐
用的地方就直接有定义了。
2. 模板定义的位置显式实例化 。这种方法不实用,不推荐。

显示实例化:

template

int Add(const int&left,const int&right)

对于其他类型照样,所以比较复杂

4. 模板总结

【优点】
1. 模板复用了代码,节省资源,更快的迭代开发, C++ 的标准模板库 (STL) 因此而产生
2. 增强了代码的灵活性
【缺陷】
1. 模板会导致代码膨胀问题,也会导致编译时间变长
2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

 
 

结束语

本篇就到此结束啦,内容有点多,相信大家通过本篇博客,对模版的认识有了进一步的理解。

最后感谢各位友友的支持,支持小编的留个赞吧!!!

相关文章:

C++之模版进阶篇

目录 前言 1.非类型模版参数 2.模版的特化 2.1概念 2.2函数模版特化 2.3 类模板特化 2.3.1 全特化和偏特化 2.3.2类模版特化应用实例 3.模版分离编译 3.1 什么是分离编译 3.2 模板的分离编译 3.3 解决方法 4. 模板总结 结束语 前言 在模版初阶我们学习了函数模版和类…...

Vue3 中的 `replace` 属性:优化路由导航的利器

嘿&#xff0c;小伙伴们&#xff01;今天给大家带来一个Vue3中非常实用的小技巧——replace属性的使用方法。在Vue Router中&#xff0c;replace属性可以帮助我们在导航时不留下历史记录&#xff0c;这对于一些特定的应用场景非常有用。话不多说&#xff0c;让我们直接进入实战…...

vite学习教程06、vite.config.js配置

前言 博主介绍&#xff1a;✌目前全网粉丝3W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容&#xff1a;Java后端、大数据、算法、分布式微服务、中间件、前端、运维等。 博主所有博客文件…...

【大数据】Flink CDC 实时同步mysql数据

目录 一、前言 二、Flink CDC介绍 2.1 什么是Flink CDC 2.2 Flink CDC 特点 2.3 Flink CDC 核心工作原理 2.4 Flink CDC 使用场景 三、常用的数据同步方案对比 3.1 数据同步概述 3.1.1 数据同步来源 3.2 常用的数据同步方案汇总 3.3 为什么推荐Flink CDC 3.4 Flink …...

JavaEE: 深入解析HTTP协议的奥秘(1)

文章目录 HTTPHTTP 是什么HTTP 协议抓包fiddle 用法 HTTP 请求响应基本格式 HTTP HTTP 是什么 HTTP 全称为"超文本传输协议". HTTP不仅仅能传输文本,还能传输图片,传输音频文件,传输其他的各种数据. 因此它广泛应用在日常开发的各种场景中. HTTP 往往是基于传输层的…...

OpenStack Yoga版安装笔记(十六)Openstack网络理解

0、前言 本文将以Openstack在Linux Bridge环境下的应用为例进行阐述。 1、Openstack抽象网络 OpenStack的抽象网络主要包括网络&#xff08;network&#xff09;、子网&#xff08;subnet&#xff09;、端口&#xff08;port&#xff09;&#xff0c;路由器&#xff08;rout…...

PEFT库和transformers库在NLP大模型中的使用和常用方法详解

PEFT&#xff08;Parameter-Efficient Fine-Tuning&#xff09;库是一个用于有效微调大型预训练语言模型的工具&#xff0c;尤其是在计算资源有限的情况下。它提供了一系列技术&#xff0c;旨在提高微调过程的效率和灵活性。以下是PEFT库的详细解读以及一些常用方法的总结&…...

静止坐标系和旋转坐标系变换的线性化,锁相环线性化通用推导

将笛卡尔坐标系的电压 [ U x , U y ] [U_x, U_y] [Ux​,Uy​] 通过旋转变换(由锁相环角度 θ P L L \theta_{PLL} θPLL​ 控制)转换为 dq 坐标系下的电压 [ U d , U q ] [U_d, U_q] [Ud​,Uq​]。这个公式是非线性的,因为它涉及到正弦和余弦函数。 图片中的推导过程主要…...

AI学习指南深度学习篇-学习率衰减的变体及扩展应用

AI学习指南深度学习篇 - 学习率衰减的变体及扩展应用 在深度学习的训练过程中&#xff0c;学习率的选择对模型的收敛速度和最终效果有重要影响。为了提升模型性能&#xff0c;学习率衰减&#xff08;Learning Rate Decay&#xff09;作为一种优化技术被广泛应用。本文将探讨多…...

成都睿明智科技有限公司真实可靠吗?

在这个日新月异的电商时代&#xff0c;抖音作为短视频与直播电商的佼佼者&#xff0c;正以前所未有的速度重塑着消费者的购物习惯。而在这片充满机遇与挑战的蓝海中&#xff0c;成都睿明智科技有限公司以其独到的眼光和专业的服务&#xff0c;成为了众多商家信赖的合作伙伴。今…...

力扣6~10题

题6&#xff08;中等&#xff09;&#xff1a; 思路&#xff1a; 这个相较于前面只能是简单&#xff0c;个人认为&#xff0c;会print打印菱形都能搞这个&#xff0c;直接设置一个2阶数组就好了&#xff0c;只要注意位置变化就好了 python代码&#xff1a; def convert(self,…...

IntelliJ IDEA 2024.2 新特性概览

文章目录 1、重点特性:1.1 改进的 Spring Data JPA 支持1.2 改进的 cron 表达式支持1.3 使用 GraalJS 作为 HTTP 客户端的执行引擎1.4 更快的编码时间1.5 K2 模式下的 Kotlin 性能和稳定性改进 2、用户体验2.1 改进的全行代码补全2.2 新 UI 成为所有用户的默认界面2.3 Search E…...

C++基础(12)——初识list

目录 1.list的简介&#xff08;引用自cplusplus官网&#xff09; 2.list的相关使用 2.1有关list的定义 2.1.1方式一&#xff08;构造某类型的空容器&#xff09; 2.1.2方式二&#xff08;构造n个val的容器&#xff09; 2.1.3方式三&#xff08;拷贝构造&#xff09; 2.1.4…...

系统架构设计师论文《论NoSQL数据库技术及其应用》精选试读

论文真题 随着互联网web2.0网站的兴起&#xff0c;传统关系数据库在应对web2.0 网站&#xff0c;特别是超大规模和高并发的web2.0纯动态SNS网站上已经显得力不从心&#xff0c;暴露了很多难以克服的问题&#xff0c;而非关系型的数据库则由于其本身的特点得到了非常迅速的发展…...

产品经理产出的原型设计 - 需求文档应该怎么制作?

需求文档&#xff0c;产品经理最终产出的文档&#xff0c;也是产品设计最终的表述形式。本次分享呢&#xff0c;就是介绍如何写好一份需求文档。 所有元件均可复用&#xff0c;可作为管理端原型设计模板&#xff0c;按照实际项目需求进行功能拓展。有需要的话可分享源文件。 …...

phenylalanine ammonia-lyase苯丙氨酸解氨酶PAL功能验证-文献精读61

Molecular cloning and characterization of three phenylalanine ammonia-lyase genes from Schisandra chinensis 五味子中三种苯丙氨酸解氨酶基因的分子克隆及特性分析 摘要 苯丙氨酸解氨酶&#xff08;PAL&#xff09;催化L-苯丙氨酸向反式肉桂酸的转化&#xff0c;是植物…...

柯桥生活口语学习之在化妆品店可以用到的韩语句子

화장품을 사고 싶어요. 我想买化妆品。 어떤 화장품을 원하세요? 您想买什么化妆品。 스킨로션을 찾고 있어요. 我想买化妆水&#xff0c;乳液。 피부 타입은 어떠세요? 您是什么皮肤类型&#xff1f; 민감성 피부예요. 我是敏感性皮肤。 평소에 쓰시는 제품은 뭐예…...

Ubuntu 安装 Docker Compose

安装Docker Compose # 删除现有的 docker-compose&#xff08;如果存在&#xff09; sudo rm -f /usr/local/bin/docker-compose ​ # 下载最新的 docker-compose 二进制文件 sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-…...

C++面试速通宝典——7

150. 数据库连接池的作用 数据库连接池的作用包括以下几个方面&#xff1a; 资源重用&#xff1a;连接池允许多个客户端共享有限的数据库连接&#xff0c;减少频繁创建和销毁连接的开销&#xff0c;从而提高资源的利用率。 统一的连接管理&#xff1a;连接池集中管理数据库连…...

毕业设计 大数据电影数据分析与可视化系统

文章目录 0 简介1 课题背景2 效果实现3 爬虫及实现4 Flask框架5 Ajax技术6 Echarts7 最后 0 简介 今天学长向大家介绍一个机器视觉的毕设项目 &#x1f6a9;基于大数据的电影数据分析与可视化系统 项目运行效果(视频)&#xff1a; 毕业设计 大数据电影评论情感分析 &#x1…...

第三届图像处理、计算机视觉与机器学习国际学术会议(ICICML 2024)

目录 重要信息 大会简介 组织单位 大会成员 征稿主题 会议日程 参会方式 重要信息 大会官网&#xff1a;www.icicml.org 大会时间&#xff1a;2024年11月22日-24日 大会地点&#xff1a;中国 深圳 大会简介 第三届图像处理、计算机视觉与机器学…...

OJ在线评测系统 微服务技术入门 单体项目改造为微服务 用Redis改造单机分布式锁登录

单体项目改造为微服务 什么是微服务 服务&#xff1a;提供某类功能的代码 微服务&#xff1a;专注于提供某类特定功能的代码 而不是把所有的代码放到同一个项目里 会把一个大的项目按照一定的功能逻辑进行划分 拆分成多个子模块 每个子模块可以独立运行 独立负责一类功能 …...

【机器学习】网络安全——异常检测与入侵防御系统

我的主页&#xff1a;2的n次方_ 随着全球互联网和数字基础设施的不断扩展&#xff0c;网络攻击的数量和复杂性都在显著增加。从传统的病毒和蠕虫攻击到现代复杂的高级持续性威胁&#xff08;APT&#xff09;&#xff0c;网络攻击呈现出更加智能化和隐蔽化的趋势。面对这样的…...

【C语言】基础篇续

最大公约数HCF与最小公倍数LCM #include<stdio.h> int main(){int n1,n2,i,hcf,lcm;printf("Enter two numbers:");scanf("%d %d",&n1,&n2);for(i 1;i < n1 & i < n2;i){if(n1 % i 0 & n2 % i 0){hcf i;lcm (n1*n2)/hc…...

文件丢失一键找回,四大数据恢复免费版工具推荐!

丢失数据的情况虽然不经常出现&#xff0c;但一旦出现都会让人头疼不已&#xff0c;而这时候&#xff0c;要如何恢复丢失的数据呢&#xff1f;一款免费好用的数据恢复工具就派上用场了&#xff01;接下来就为大家推荐几款好用的数据恢复工具&#xff01; 福昕数据恢复 直达链…...

【学习笔记】手写一个简单的 Spring MVC

目录 一、什么是Spring MVC &#xff1f; Spring 和 Spring MVC 的区别&#xff1f; Spring MVC 的运行流程&#xff1f; 二、实现步骤 1. DispatcherServlet 1. 创建一个中央分发器 拦截所有请求 测试 2. 接管 IOC 容器 1. 创建配置文件 2. 修改 web.xml 配置文件 …...

编程究竟难在哪里?

目录 一、将现实问题转化为代码二、应对需求的不断变化三、设计新算法的挑战结语 编程之难&#xff0c;常被概括为三个方面&#xff1a;首先&#xff0c;是将现实世界的问题转化为计算机语言的挑战&#xff1b;其次&#xff0c;是需求不断变化所带来的适应性难题&#xff1b;最…...

C#医学影像分析源码,医院影像中心PACS系统源码

医学影像系统源码&#xff0c;影像诊断系统PACS源码&#xff0c;C#语言&#xff0c;C/S架构的PACS系统全套源代码。 PACS系统是医院影像科室中应用的一种系统&#xff0c;主要用于获取、传输、存档和处理医学影像。它通过各种接口&#xff0c;如模拟、DICOM和网络&#xff0c;以…...

WooCommerce与wordpress是什么关系

WooCommerce与WordPress之间的关系非常紧密&#xff0c;因为WooCommerce实际上是一个为WordPress设计的插件。WordPress是一个内容管理系统(CMS)&#xff0c;广泛用于创建各种类型的网站&#xff0c;包括博客、企业网站等。而WooCommerce则是一个免费且开源的电子商务插件&…...

Web常见的攻击方式及防御方法

Web常见的攻击方式及防御方法如下&#xff1a; 1. 跨站脚本&#xff08;XSS&#xff09; 攻击方式&#xff1a;恶意代码被注入到网页中&#xff0c;用户浏览时执行该代码&#xff0c;导致窃取用户信息、伪造页面等。防御&#xff1a; 对用户输入严格过滤、转义。使用安全的编…...