【C++入门到精通】异常 | 异常的使用 | 自定义异常体系 [ C++入门 ]
阅读导航
- 引言
- 一、C++异常的概念
- 二、异常的使用
- 1. 异常的抛出和捕获
- (1)throw
- (2)try-catch
- (3)catch(. . .)
- (4)异常的抛出和匹配原则
- (5)在函数调用链中异常栈展开匹配原则
- 2. 异常的重新抛出
- 3. 异常安全
- 4. 异常规范
- 三、自定义异常体系
- 1. 创建基类异常
- 2. 创建派生异常
- 3. 抛出异常
- 4. 捕获和处理异常
- 5. 自定义异常体系示例
- 四、C++标准库的异常体系
- 五、异常的优缺点
- 1. C++异常的优点
- 2. C++异常的缺点
- 3. 总结
- 温馨提示
引言
在C++编程中,异常处理是一项重要的技术,它允许我们更好地应对程序运行过程中可能出现的错误和异常情况。本文将介绍C++中异常处理的基本概念、语法和最佳实践。我们将深入探讨try-catch块的使用方式,以及如何抛出和捕获不同类型的异常。
希望本文能够帮助您更好地理解和运用C++异常处理机制,并为您的编程工作带来便利和效益。祝您阅读愉快!
一、C++异常的概念
C++异常是一种用于处理程序运行时错误和异常情况的机制。当程序在执行过程中遇到无法正常处理的错误时,可以通过抛出异常来中断当前的执行流程,并将控制权转交给异常处理器。异常处理器可以捕获并处理异常,从而使程序能够优雅地处理错误情况,避免崩溃或数据丢失。异常可以表示各种不同类型的错误,例如除以零、访问不存在的内存地址、文件打开失败等。
二、异常的使用
如果有一个块抛出一个异常,捕获异常的方法会使用 try
和 catch
关键字。try
块中放置可能抛出异常的代码,try
块中的代码被称为保护代码。
1. 异常的抛出和捕获
(1)throw
throw
关键字用于抛出异常。当程序在执行过程中遇到无法正常处理的错误时,可以通过throw
语句抛出一个异常,让异常处理器来捕获并处理这个异常。例如:
if (count == 0) {throw std::runtime_error("Divide by zero exception");
}
在上面的例子中,如果count等于0,则会抛出一个std::runtime_error异常,并附带异常信息“Divide by zero exception”。
(2)try-catch
try-catch
块用于捕获和处理异常。try
块用于包含可能引发异常的代码,catch
块则用于捕获和处理特定类型的异常。例如:
try {// 可能引发异常的代码
} catch (std::exception& e) {// 捕获std::exception及其派生类的异常std::cerr << "Exception caught: " << e.what() << std::endl;
} catch (...) {// 捕获其他类型的异常std::cerr << "Unknown exception caught" << std::endl;
}
在上面的例子中,try
块包含可能引发异常的代码,catch
块捕获std::exception
及其派生类的异常,并输出异常信息。如果没有合适的catch
块来处理异常,则会跳转到最近的catch(...)
块。
(3)catch(. . .)
catch(...)
块用于捕获任何类型的异常。如果程序抛出了一个未被其他catch块捕获的异常,则会跳转到最近的catch(...)
块,并执行相关的异常处理代码。
(4)异常的抛出和匹配原则
- 异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个
catch
的处理代码。 - 被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
- 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。(这里的处理类似于函数的传值返回)
- catch(…)可以捕获任意类型的异常,问题是不知道异常错误是什么。
- 实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类对象,使用基类捕获,这个在实际中非常实用。
(5)在函数调用链中异常栈展开匹配原则
- 首先检查
throw
本身是否在try
块内部,如果是再查找匹配的catch
语句。如果有匹配的,则调到catch的地方进行处理。 - 没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch。
- 如果到达main函数的栈,依旧没有匹配的,则终止程序。
- 找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。
🚨🚨注意:上述这个沿着调用链查找匹配的catch
子句的过程称为栈展开。所以实际中我们最后都要加一个catch(…)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。
2. 异常的重新抛出
在C++中,异常的重新抛出是指在一个catch块中捕获到一个异常后,再次将它抛出,以便由更高层次的异常处理器来处理。这种重新抛出异常的操作可以在catch
块中使用throw
语句来实现。
⭕重新抛出异常的语法如下:
try {// 可能引发异常的代码
} catch (ExceptionType1& e) {// 异常处理代码throw; // 重新抛出异常
} catch (ExceptionType2& e) {// 异常处理代码throw; // 重新抛出异常
}
在上面的代码中,当在catch
块中捕获到ExceptionType1类型的异常时,我们可以选择重新抛出该异常,让更高层的异常处理器来处理。通过throw
语句,异常会被重新抛出并继续向上寻找匹配的catch块。
重新抛出异常的好处在于,在某些情况下,当前的catch块可能无法完全处理异常,并希望由更上层的异常处理器来处理。这样可以将异常传递给更高层的代码进行处理,而不是简单地在当前的catch块中忽略掉异常。
🚨注意:在重新抛出异常时,可以选择不指定异常类型,即使用throw
;来重新抛出原始的异常。这样做的好处是可以保持异常的类型和信息不变,使得更高层的异常处理器可以正常地捕获和处理异常。
3. 异常安全
在C++中,异常安全是指程序在抛出异常时仍然能够保证程序的正确性和资源的释放。异常安全是一个重要的编程概念,因为在实际开发中,程序运行过程中难免会遇到各种异常情况,如内存不足、IO错误等,而这些异常可能会导致程序崩溃或者产生未知的错误,给程序的稳定性和可维护性带来很大的挑战。
为了提高程序的异常安全性,我们需要采取一些措施,主要包括以下几个方面:
🍁 使用RAII技术
RAII(Resource Acquisition Is Initialization)是一种资源获取即初始化的技术,通过C++对象的构造函数获取资源,利用析构函数自动释放资源。这样可以确保资源的正确释放,即使在抛出异常的情况下也能够保证资源的正确释放。比如使用std::unique_ptr智能指针管理内存,std::lock_guard管理锁等。(关于RAII我们智能指针这篇文章有所讲解)
🍁不要泄漏资源
在程序执行过程中,如果没有正确地释放资源,就会导致资源泄漏,进而影响程序的正确性和稳定性。因此,在编写程序时,要确保所有获取的资源都要正确释放,以避免资源泄漏。
🍁异常处理
在程序中,如果遇到异常情况,则需要正确地处理这些异常。一般来说,我们可以使用try-catch语句块来捕获并处理异常,确保程序在抛出异常时仍然能够保证程序的正确性和资源的释放。
4. 异常规范
异常规范(Exception Specification)是一种在C++函数声明中指定函数可能抛出的异常类型的方法。异常规范可以告诉调用者该函数可能会抛出哪些异常,以便调用者能够适当地处理这些异常。在C++中,有两种类型的异常规范:动态异常规范和静态异常规范。
🍪动态异常规范(Dynamic Exception Specification):
动态异常规范使用throw
关键字在函数声明中列出函数可能抛出的异常类型。例如:
void functionName() throw(ExceptionType1, ExceptionType2);
上述代码表示函数functionName
可能会抛出ExceptionType1
和ExceptionType2
类型的异常。如果函数抛出了未在异常规范中列出的异常,就会调用std::unexpected()
函数,该函数默认会调用std::terminate()
函数终止程序。
🍪静态异常规范(Static Exception Specification):
静态异常规范使用noexcept关键字指示函数不会抛出任何异常。例如:
void functionName() noexcept;
上述代码表示函数functionName不会抛出任何异常。这样的函数被称为不抛出异常的函数,编译器可以对其进行更多的优化。
在C++11之后,推荐使用noexcept
来指示函数不会抛出异常,而避免使用动态异常规范。同时,C++11引入了std::nothrow
关键字,用于在发生异常时返回一个null
指针,而不是抛出异常。
🚨注意:如果函数声明了静态异常规范,但实际上抛出了异常,程序会调用std::terminate()
函数终止程序。
三、自定义异常体系
✅在C++中,可以通过自定义异常类来创建自己的异常体系。自定义异常体系可以用于对不同类型的异常进行分类和处理。在实际的程序中都会定义一套继承的规范体系。这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了。
⭕下面是创建自定义异常体系的步骤
1. 创建基类异常
创建一个基类异常,作为自定义异常体系的根。这个基类异常可以是std::exception的子类或者直接继承自std::exception。例如:
class MyException : public std::exception {
public:virtual const char* what() const throw() {return "My exception occurred";}
};
在基类异常中,通常会重写what()
函数,该函数返回异常的描述信息。
2. 创建派生异常
根据需要,可以创建多个派生异常类,用于表示不同类型的异常。这些派生异常类可以继承自基类异常或者其他已有的异常类。例如:
class OutOfRangeException : public MyException {
public:virtual const char* what() const throw() {return "Out of range exception";}
};class NullPointerException : public MyException {
public:virtual const char* what() const throw() {return "Null pointer exception";}
};
在派生异常类中,也可以重写what()
函数,以提供特定异常的描述信息。
3. 抛出异常
在程序中遇到异常情况时,可以使用throw
语句抛出自定义的异常对象。例如:
void myFunction() {throw OutOfRangeException();
}
以上代码示例在myFunction()
函数中抛出了一个OutOfRangeException
异常对象。
4. 捕获和处理异常
在调用可能引发异常的代码时,可以使用try-catch
语句块捕获并处理异常。例如:
try {myFunction();
} catch (MyException& ex) {std::cout << "Caught exception: " << ex.what() << std::endl;
}
以上代码示例在调用myFunction()
时捕获并处理了MyException
及其派生异常的对象。
自定义异常体系可以根据具体需求进行扩展和细化,以提供更好的异常分类和处理能力。通过创建不同类型的异常类,可以更好地组织和处理程序中的异常情况。
5. 自定义异常体系示例
#include <iostream>
#include <string>
#include <ctime>
#include <chrono>
#include <thread>using namespace std;// 自定义异常基类
class Exception
{
public:// 构造函数,接收错误信息和错误码作为参数Exception(const string& errmsg, int id): _errmsg(errmsg), _id(id){}// 返回异常信息的函数virtual string what() const{return _errmsg;}protected:string _errmsg; // 异常信息int _id; // 异常码
};// 派生自Exception的SqlException异常类
class SqlException : public Exception
{
public:// 构造函数,接收错误信息、错误码和SQL语句作为参数SqlException(const string& errmsg, int id, const string& sql): Exception(errmsg, id), _sql(sql){}// 返回异常信息的函数virtual string what() const{string str = "SqlException:";str += _errmsg;str += "->";str += _sql;return str;}private:const string _sql; // SQL语句
};// 派生自Exception的CacheException异常类
class CacheException : public Exception
{
public:// 构造函数,接收错误信息和错误码作为参数CacheException(const string& errmsg, int id): Exception(errmsg, id){}// 返回异常信息的函数virtual string what() const{string str = "CacheException:";str += _errmsg;return str;}
};// 派生自Exception的HttpServerException异常类
class HttpServerException : public Exception
{
public:// 构造函数,接收错误信息、错误码和请求类型作为参数HttpServerException(const string& errmsg, int id, const string& type): Exception(errmsg, id), _type(type){}// 返回异常信息的函数virtual string what() const{string str = "HttpServerException:";str += _type;str += ":";str += _errmsg;return str;}private:const string _type; // 请求类型
};// SQL管理函数
void SQLMgr()
{srand(time(0));if (rand() % 7 == 0){// 如果随机数满足条件,抛出SqlException异常throw SqlException("权限不足", 100, "select * from name = '张三'");}
}// 缓存管理函数
void CacheMgr()
{srand(time(0));if (rand() % 5 == 0){// 如果随机数满足条件,抛出CacheException异常throw CacheException("权限不足", 100);}else if (rand() % 6 == 0){// 如果随机数满足条件,抛出CacheException异常throw CacheException("数据不存在", 101);}SQLMgr();
}// HTTP服务器函数
void HttpServer()
{// ...srand(time(0));if (rand() % 3 == 0){// 如果随机数满足条件,抛出HttpServerException异常throw HttpServerException("请求资源不存在", 100, "get");}else if (rand() % 4 == 0){// 如果随机数满足条件,抛出HttpServerException异常throw HttpServerException("权限不足", 101, "post");}CacheMgr();
}int main()
{while (1){this_thread::sleep_for(chrono::seconds(1));try {// 调用HttpServer函数可能会抛出异常HttpServer();}catch (const Exception& e) {// 捕获Exception及其派生类的异常对象cout << e.what() << endl; // 输出异常信息}catch (...) {// 捕获其他类型的异常cout << "Unkown Exception" << endl;}}return 0;
}
这是一个基于C++的自定义异常体系。在该代码中,自定义了三个异常类,分别是SqlException
、CacheException
和HttpServerException
,这些异常类都派生自基类Exception
。通过自定义异常类,可以更准确地捕获异常,同时也可以对不同类型的异常进行不同的处理。
在代码中,SqlException
用于处理SQL语句相关的异常,CacheException
用于处理缓存相关的异常,HttpServerException
用于处理HTTP服务器相关的异常。每个异常类都有一个构造函数,用于初始化异常信息和错误码等参数。在捕获异常时,可以根据异常类型来选择相应的处理方式,比如输出错误信息、记录日志、重试操作等等。
四、C++标准库的异常体系
⭕C++ 提供了一系列标准的异常,定义在 中,我们可以在程序中使用这些标准的异常。它们是以父子类层次结构组织起来的,如下图所示:
下表是对上面层次结构中出现的每个异常的说明:
异常类型 | 描述 |
---|---|
std::exception | 所有异常类的基类 |
std::logic_error | 程序逻辑错误 |
std::invalid_argument | 无效参数 |
std::domain_error | 域错误 |
std::length_error | 长度错误 |
std::out_of_range | 超出范围 |
std::future_error | 异步执行错误 |
std::runtime_error | 运行时错误 |
std::range_error | 范围错误 |
std::overflow_error | 溢出错误 |
std::underflow_error | 下溢错误 |
std::regex_error | 正则表达式错误 |
std::bad_alloc | 内存分配错误 |
std::bad_cast | 类型转换错误 |
std::bad_exception | 未捕获的异常 |
std::bad_function_call | 错误的函数调用 |
std::bad_typeid | typeid操作错误 |
std::bad_weak_ptr | weak_ptr错误 |
std::ios_base::failure | I/O流错误 |
std::system_error | 系统调用错误 |
std::filesystem::filesystem_error | 文件系统错误 |
std::experimental::filesystem::filesystem_error | 实验性文件系统错误 |
五、异常的优缺点
异常是一种处理程序运行时错误的机制,它提供了一种在程序中处理异常情况的方式。以下是异常的优点和缺点:
1. C++异常的优点
- 异常对象定义好了,相比错误码的方式可以清晰准确的展示出错误的各种信息,甚至可以包含堆栈调用的信息,这样可以帮助更好的定位程序的bug。
- 异常可以提高代码的可读性和可维护性,将错误处理代码与正常逻辑分离开来,使代码更加清晰易懂。
- 异常可以通过层级结构进行处理,允许异常在不同的层次上被捕获和处理,从而提高了程序的灵活性和扩展性。
2. C++异常的缺点
- 异常可能会导致性能问题,因为在发生异常时需要执行一些额外的操作,如调用析构函数、回收内存等,这些操作会增加程序的开销。
- 异常可能会影响代码的可移植性,因为异常处理机制在不同的编译器和操作系统上可能有所不同,需要针对不同的平台进行调整。
- 异常可能会导致程序的安全性问题,因为异常可以破坏程序的状态,可能会被恶意利用。此外,异常也可能会隐藏错误,使得程序的调试和测试变得更加困难。
- 异常会导致程序的执行流乱跳,并且非常的混乱,并且是运行时出错抛异常就会乱跳。这会导致我们跟踪调试时以及分析程序时,比较困难。
3. 总结
综上所述,异常总体而言,利大于弊,所以工程中我们还是鼓励使用异常的。在使用异常时,我们应该权衡利弊,根据实际情况选择合适的处理方式,保证程序的健壮性和安全性。
温馨提示
感谢您对博主文章的关注与支持!另外,我计划在未来的更新中持续探讨与本文相关的内容,会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!
再次感谢您的支持和关注。期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
相关文章:
【C++入门到精通】异常 | 异常的使用 | 自定义异常体系 [ C++入门 ]
阅读导航 引言一、C异常的概念二、异常的使用1. 异常的抛出和捕获(1)throw(2)try-catch(3)catch(. . .)(4)异常的抛出和匹配原则(5)在函数调用链中异常栈展开…...
NX二次开发 Block UI 指定方位控件的应用
一、概述 NX二次开发中一般都是多个控件的组合,这里我首先对指定方位控件进行说明并结合选择对象控件,具体如下图所示。 二、实现功能获取方位其在选择面上原点的目标 2.1 在initialize_cb()函数中进行初始化,实现对象选择过滤面 //过滤平…...
2024年【R2移动式压力容器充装】模拟考试及R2移动式压力容器充装实操考试视频
题库来源:安全生产模拟考试一点通公众号小程序 2024年【R2移动式压力容器充装】模拟考试及R2移动式压力容器充装实操考试视频,包含R2移动式压力容器充装模拟考试答案和解析及R2移动式压力容器充装实操考试视频练习。安全生产模拟考试一点通结合国家R2移…...
数仓工具—Hive进阶之StorageHandler(23)
Storage Handler 引入Storage Handler,Hive用户使用SQL的方式读写外部数据源, 例如ElasticSearch、 Kafka、HBase等数据源的查询对非专业开发是有一定门槛的,借助Storage Handler,他们有了一种方便快捷的手段查询数据,Storage Handler作为Hive的存储插件,我们需要的时候直…...
科技创新创业
科技创新创业是一个涉及多个方面的过程,主要包括以下几个方面: 创意产生:创业的起始点通常是一个新的创意或想法,这可能是一个新的产品、服务或技术的概念。这个创意需要独特且具有商业潜力。市场调研:一旦有了创意&a…...
高校电力能耗监测精细化管理系统,提升能源利用效率的利器
电力是高校不可离开的重要能源,为学校相关管理人员提供在线用能查询统计等服务。通过对学校照明用电、空调用电等数据的采集、监控、分析,为学校电能管理制定合理的能源政策提供参考。同时,也可以培养学生的节能意识,学校后勤电力…...
Java_Swing程序设计
swing组件允许编程人员在跨平台时指定统一的外观和风格。 Swing组件通常被称为轻量级组件, JFrame在程序中的语法格式: JFrame jfnew JFrame(title); Container containerjf.getContentPane(); jf:JFrame类的对象 container:Container类的对象。 J…...
ZeroBind:DTI零样本预测器
现有的药物-靶点相互作用(DTI)预测方法通常无法很好地推广到新的(unseen)蛋白质和药物。 在这项研究中,作者提出了一种具有子图匹配功能的蛋白质特异性元学习框架 ZeroBind,用于根据其结构预测蛋白质-药物相…...
Win10子系统Ubuntu实战(一)
在 Windows 10 中安装 Ubuntu 子系统(Windows Subsystem for Linux,简称 WSL)有几个主要的用途和好处:Linux 环境的支持、跨平台开发、命令行工具、测试和验证、教育用途。总体而言,WSL 提供了一种将 Windows 和 Linux…...
[足式机器人]Part3 机构运动学与动力学分析与建模 Ch00-2(3) 质量刚体的在坐标系下运动
本文仅供学习使用,总结很多本现有讲述运动学或动力学书籍后的总结,从矢量的角度进行分析,方法比较传统,但更易理解,并且现有的看似抽象方法,两者本质上并无不同。 2024年底本人学位论文发表后方可摘抄 若有…...
云计算历年题整理
目录 第一大题 第一大题HA计算 给出计算连接到EC2节点的EBS的高可用性(HA)的数学公式,如场景中所述;计算EC2节点上的EBS的高可用性(HA);场景中80%的AWS EC2节点用于并行处理,总共有100个虚拟中央处理单元(vCPUs)用于处理数据&a…...
2401vim,vim重要修改更新大全
原文 2023 更好的UTF-16支持 添加strutf16len()和utf16idx(),并在byteidx(),byteidxcomp()和charidx()中添加utf16标志,在内置.txt文档中. 添加crypymethod xchacha20v2 与xchacha20基本相同,但更能抵御libsodium的变化. 2022 添加"smoothscroll" 用鼠标滚动…...
安卓多用户管理之Userinfo
目录 前言Userinfo----用户信息1.1 属性1.2 构造器1.3 信息的判断及获取方法1.3.1 获取默认用户类型1.3.2 基础信息判断 1.4 序列化部分 总结 前言 UserManagerService内部类UserData中有一个Userinfo类型的info参数,在UserData中并未有所体现,但在后续…...
JavaScript-流程控制-笔记
1.流程语句的分类 顺序结构 分支结构 循环结构 2.if语句 1)if结构 if( 条件 ){ // 条件成立执行的代码 } 2)if else 结构 if( 条件 ){ // 条件成立执行的代码 }else{ // 条件不成…...
springboot + vue3实现增删改查分页操作
springboot vue3实现增删改查分页操作 环境最终实现效果实现功能主要框架代码实现数据库后端前端 注意事项 环境 jdk17 vue3 最终实现效果 实现功能 添加用户,禁用,启用,删除,编辑,分页查询 主要框架 后端 spri…...
leetcode01-重复的子字符串
题目链接:459. 重复的子字符串 - 力扣(LeetCode) 一般思路: 如果存在k是S的字串,记k的长度为s,S的长度为n,则一定有n是s的倍数,且满足对于j∈[s,n],一定存在s[j]s[j-s]; …...
目标检测数据集 - 夜间行人检测数据集下载「包含VOC、COCO、YOLO三种格式」
数据集介绍:夜间、低光行人检测数据集,真实场景高质量图片数据,涉及场景丰富,比如夜间街景行人、夜间道路行人、夜间遮挡行人、夜间严重遮挡行人数据;适用实际项目应用:公共场所监控场景下夜间行人检测项目…...
【YOLO系列】 YOLOv4思想详解
前言 以下内容仅为个人在学习人工智能中所记录的笔记,先将目标识别算法yolo系列的整理出来分享给大家,供大家学习参考。 本文未对论文逐句逐段翻译,而是阅读全文后,总结出的YOLO V4论文的思路与实现路径。 若文中内容有误…...
查询json数组
步骤一:创建表格 首先,我们需要创建一个表格来存储包含JSON对象数组的数据。可以使用以下代码创建一个名为 my_table 的表格: CREATE TABLE my_table (id INT PRIMARY KEY AUTO_INCREMENT,json_data JSON ); 上述代码创建了一个包含两个列的…...
Docker mysql 主从复制
目录 介绍:为什么需要进行mysql的主从复制 主从复制原理: ✨主从环境搭建 主从一般面试问题: 介绍:为什么需要进行mysql的主从复制 在实际的生产中,为了解决Mysql的单点故障已经提高MySQL的整体服务性能ÿ…...
第7章-第1节-Java中的异常处理
1、异常Exception概述: 1)、异常的概念: 现实生活中万物在发展和变化会出现各种各样不正常的现象。 例如:人的成长过程中会生病。 实际工作中,遇到的情况不可能是非常完美的。 比如:你写的某个模块&…...
使用python生成一个月度账单消费金额柱状图表
阿里云月度账单根据月份、消费金额(可开票)生成一个柱状图表 import pandas as pd import matplotlib.pyplot as plt import os# 设置中文字体 plt.rcParams[font.sans-serif] [SimHei] # 用于显示中文的宋体# 获取当前工作目录下所有CSV文件 csv_fil…...
将一个独立的磁盘添加到已有的 `/` 分区
将一个独立的磁盘添加到已有的 / 分区是比较复杂的,因为 / 分区已经是一个逻辑卷(LVM)。在这种情况下,可以扩展现有的 LVM 体积组(Volume Group),然后扩展 / 逻辑卷(Logical Volume&…...
AI智能电销器人需要注意哪些问题呢
随着科技的不断发展,人们出行变得越来越方便,市面上很多产品也越来越智能化,高科技的产品不仅改变了我们的生活方式而且也改变了企业的竞争方式,很多的企业尤其是电销行业中的大佬己经意识到了AI电销机器人的好处,因此…...
呼叫中心研究分析:到2027年市场规模预计将达4966亿美元
由于业务运营中以客户为中心的方法的兴起,呼叫中心市场近年来出现了显着增长。随着对客户满意度的日益重视,全球对呼叫中心服务的需求猛增。在本次分析中,我们将从全球和中国的角度审视呼叫中心市场的发展趋势。全球市场: 到 2027…...
工业数据采集分析——工厂大脑 提升综合经济效益
随着企业对数字化的认知越来越清晰,对工业数智化的战略越来越明确,企业的诉求也在发生转变。中国的工业企业经过近几十年的发展,自动化、信息化,以及一些基础的数据系统建设在不同的行业中慢慢地推进。近几年,工业企业…...
python系列教程218——生成器表达式
朋友们,如需转载请标明出处:https://blog.csdn.net/jiangjunshow 声明:在人工智能技术教学期间,不少学生向我提一些python相关的问题,所以为了让同学们掌握更多扩展知识更好地理解AI技术,我让助理负责分享…...
jquery 实现简单的标签页效果
实现 <!DOCTYPE html> <html> <head><title>jq 实现简单的标签页效果</title><script src"/jquery/jquery-1.11.1.min.js"></script><style>.tab {cursor: pointer;width:100px;height:30px;float:left;text-align…...
C++ Web框架Drogon初体验笔记
这段时间研究了一下C的Web框架Drogon。从设计原理上面来说和Python的Web框架是大同小异的,但是难点在于编译项目上面,所以现在记录一下编译的过程。下面图是我项目的目录。其中include放的是头文件,src放的是视图文件,static放的是…...
x-cmd pkg | busybox - 嵌入式 Linux 的瑞士军刀
目录 简介首次用户功能特点竞品和相关作品 进一步阅读 简介 busybox 是一个开源的轻量级工具集合,集成了一批最常用 Unix 工具命令,只需要几 MB 大小就能覆盖绝大多数用户在 Linux 的使用,能在多款 POSIX 环境的操作系统(如 Linu…...
用织梦做网站都需要用什么/广州网站建设方案维护
程序员可以做哪些副业? 作为一名程序员,除了敲代码之外还应该有一些副业。什么是副业?副业就是主要事业以外附带经营的事业。我们都是程序员,大多数都是普通人,都在替别人打工,虽然收入在别人眼中挺高&…...
wordpress开发视频教程/网页搜索引擎大全
一、痔疮用药市场规模 痔疮,是人类特有的常见病、多发病。据有关普查资料表明,痔疮等肛门直肠疾病的发病率为59.1%,痔疮占所有肛肠疾病中的87.25%,而其中又以内痔最为常见,占所有肛肠疾病的52.19%。男女均可得病&#…...
wordpress feed 地址/抖音关键词优化排名靠前
XSLT是XML文档转换语言,虽然不能直接定义显示方式,但可以通过将XML文档转换成能够显示的格式,以达到指定样式的目的。由于XSLT的目的是指定样式,因此并不能说是完全的通用转换语言。目前来说,XML文档转换的许多场合下都…...
佛山营销网站建设服务/竞价网络推广外包
此笔记出自《深入理解java虚拟机 第二版》,仅做摘要整理,详细了解可购买相关书籍。 图片扎堆,一是为了让文字更加紧凑,二是为了学习完文字知识后能单纯看图回顾,及时复习,三是增加不同类型之间对比。 三连问…...
wordpress新手基础入门视频教程/线上营销推广方式
直角坐标是常用的坐标法,但是对于一些特别的问题,在直角坐标系下处理就显得有点笨拙了。这个时候,不妨试试极坐标。它可以使得问题变得出乎意料的简洁,也能让问题直观和清晰起来。 极坐标 什么是极坐标 概念来自百度百科ÿ…...
wordpress与dede哪个好用/网络营销案例题
通过DevExpress WPF Controls,你能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件的衍伸产品,还是以数据为中心的商业智能产品,都能通过De…...