[C++]C++工具之对异常情况的处理(throw、catch、try)以及用命名空间避免同名冲突

一、C++ 异常处理😊


1.1 定义

C++ 中的异常处理用于应对程序运行中的异常情况(如除零、数组越界等),通过 try-catch 机制捕获和处理错误,防止程序崩溃。
异常是程序运行时意外发生的事件,可以通过抛出(throw)和捕获(catch)机制处理。


1.2 通俗解释

  • 抛异常(throw): 就像在程序运行时发现问题了,扔出一个问题给系统处理。
  • 捕获异常(catch): 系统接收到这个问题后,根据你的代码去解决问题。
  • try 块: 这是一个保护块,把可能出错的代码放在这里,避免程序直接崩溃。

1.3 固定格式

try {// 可能抛出异常的代码throw exception_object;  // 抛出异常
} catch (exception_type variable_name) {// 捕获异常并处理
} catch (...) {// 捕获所有类型的异常(可选)
}
  • throw:用来抛出异常,可以是内置类型(如整数、字符串)或自定义类型(如对象)。
  • catch:用来捕获异常,必须匹配 throw 的类型,或者用 ... 捕获所有类型。
  • try:将可能出错的代码块包裹起来。

1.4 注意点

  1. 匹配顺序:

    • catch 子句是按顺序匹配的,第一个匹配的会被执行。
    • catch (...) 必须放在最后,用于捕获所有未明确处理的异常。
  2. 异常传递:

    • 如果函数中抛出的异常没有被处理,会向调用者函数传播,直到找到合适的 catch 块。
  3. 自定义异常类:

    • 可以通过定义自己的类,抛出更具体的异常信息。

1.5C++中的主要异常类型

1.5.1. 内置类型的异常

1. 整数异常

可以直接抛出整数类型的异常,用于简单错误标识。

#include <iostream>
using namespace std;int main() {try {throw 42;  // 抛出整数异常} catch (int e) {  // 捕获整数类型的异常cout << "Caught integer exception: " << e << endl;}return 0;
}
/*
输出:
Caught integer exception: 42
*/

2. 字符串异常

可以抛出字符串(如 const char*std::string)类型的异常,通常用来描述错误信息。

#include <iostream>
using namespace std;int main() {try {throw "An error occurred";  // 抛出字符串异常} catch (const char* e) {  // 捕获字符串类型异常cout << "Caught exception: " << e << endl;}return 0;
}
/*
输出:
Caught exception: An error occurred
*/

3. 浮点数异常

可以直接抛出浮点类型,用于表示数值相关的错误。

#include <iostream>
using namespace std;int main() {try {throw 3.14;  // 抛出浮点数异常} catch (double e) {  // 捕获浮点类型异常cout << "Caught floating-point exception: " << e << endl;}return 0;
}
/*
输出:
Caught floating-point exception: 3.14
*/

4. 布尔类型异常

布尔类型也可以被抛出,通常用作简单的状态标识。

#include <iostream>
using namespace std;int main() {try {throw true;  // 抛出布尔类型异常} catch (bool e) {cout << "Caught boolean exception: " << (e ? "true" : "false") << endl;}return 0;
}
/*
输出:
Caught boolean exception: true
*/


1.5.2. 标准库类型的异常

C++ 提供了一些预定义的异常类,它们位于标准库中,包含在 <stdexcept><exception> 等头文件中。以下是常用的标准异常类型:

1. std::exception
  • 是所有标准异常类的基类。
  • 通常作为通用异常捕获的类型。
    #include <iostream>
    #include <exception>
    using namespace std;int main() {try {throw exception();  // 抛出标准异常} catch (exception& e) {  // 捕获标准异常cout << "Caught standard exception: " << e.what() << endl;}return 0;
    }
    /*
    输出:
    Caught standard exception: std::exception
    */

    2. std::logic_error
  • 表示程序逻辑错误,通常由于程序员的疏忽引起。
  • 例如:访问空指针、非法参数等。
#include <iostream>
#include <stdexcept>
using namespace std;int main() {try {throw logic_error("Logic error occurred");  // 抛出逻辑错误} catch (logic_error& e) {cout << "Caught logic_error: " << e.what() << endl;}return 0;
}
/*
输出:
Caught logic_error: Logic error occurred
*/
 3. std::runtime_error
  • 表示程序运行时的错误。
  • 例如:文件未找到、网络中断等。
#include <iostream>
#include <stdexcept>
using namespace std;int main() {try {throw runtime_error("Runtime error occurred");  // 抛出运行时错误} catch (runtime_error& e) {cout << "Caught runtime_error: " << e.what() << endl;}return 0;
}
/*
输出:
Caught runtime_error: Runtime error occurred
*/

4. std::bad_alloc
  • 表示内存分配失败。
  • new 操作符无法分配内存时,抛出此异常。
#include <iostream>
#include <new>
using namespace std;int main() {try {int* arr = new int[1000000000000000];  // 请求过多内存} catch (bad_alloc& e) {cout << "Caught bad_alloc: " << e.what() << endl;}return 0;
}
/*输出:
Caught bad_alloc: std::bad_alloc
*/

5. std::out_of_range
  • 表示访问容器时超出有效范围。
  • 例如:访问数组中不存在的元素。
#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;int main() {try {vector<int> vec = {1, 2, 3};cout << vec.at(10);  // 超出范围} catch (out_of_range& e) {cout << "Caught out_of_range: " << e.what() << endl;}return 0;
}
/*输出:
Caught out_of_range: vector::_M_range_check: __n (which is 10) >= this->size() (which is 3)
*/

1.5.3自定义类型的异常

用户可以自定义类作为异常类型,用于处理程序特定的错误场景。

1.自定义异常类
#include <iostream>
#include <string>
using namespace std;class MyException {string message;
public:MyException(string msg) : message(msg) {}string getMessage() const { return message; }
};int main() {try {throw MyException("Custom exception occurred!");  // 抛出自定义异常} catch (MyException& e) {cout << "Caught exception: " << e.getMessage() << endl;}return 0;
}
/*输出:
Caught exception: Custom exception occurred!
*/

1.5.4 捕获所有类型的异常

1.使用 catch(...) 捕获任意类型的异常。
#include <iostream>
using namespace std;int main() {try {throw 3.14;  // 抛出浮点数异常} catch (...) {  // 捕获所有异常cout << "Caught an unknown exception." << endl;}return 0;
}
/*输出:
Caught an unknown exception.
*/

1.6总结

常见的异常类型

1.6.1内置类型:

  1. 整数、浮点数、字符串、布尔值。

1.6.2标准库类型:

  1. std::exception(基类)。
  2. std::logic_error(逻辑错误)。
  3. std::runtime_error(运行时错误)。
  4. std::bad_alloc(内存分配失败)。
  5. std::out_of_range(超出范围错误)。

1.6.3用户自定义类型:

  1. 用户可以定义自己的类来表示异常类型。

1.7捕获规则

  1. 使用匹配的 catch 处理具体异常。
  2. 使用 catch(...) 捕获所有未处理的异常。

1.7.1综合代码示例与解析:

#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
using namespace std;// 自定义异常类
class MyException {string message;
public:MyException(string msg) : message(msg) {}string getMessage() const { return message; }
};int main() {try {// Uncomment (取消注释) 以下一行代码逐个测试不同类型的异常// throw 42;                          // 整数类型异常// throw 3.14;                        // 浮点数类型异常// throw "An error occurred!";        // 字符串异常// throw string("String object error"); // std::string 异常// throw logic_error("Logic error");  // 标准库逻辑错误// throw runtime_error("Runtime error"); // 标准库运行时错误// throw out_of_range("Out of range error"); // 超出范围异常// throw bad_alloc();                 // 内存分配失败异常throw MyException("Custom exception occurred!"); // 自定义异常} catch (int e) {cout << "Caught an integer exception: " << e << endl;} catch (double e) {cout << "Caught a floating-point exception: " << e << endl;} catch (const char* e) {cout << "Caught a C-string exception: " << e << endl;} catch (string& e) {cout << "Caught a string object exception: " << e << endl;} catch (logic_error& e) {cout << "Caught logic_error: " << e.what() << endl;} catch (runtime_error& e) {cout << "Caught runtime_error: " << e.what() << endl;} catch (out_of_range& e) {cout << "Caught out_of_range: " << e.what() << endl;} catch (bad_alloc& e) {cout << "Caught bad_alloc: " << e.what() << endl;} catch (MyException& e) {cout << "Caught custom exception: " << e.getMessage() << endl;} catch (...) { // 捕获所有其他类型的异常cout << "Caught an unknown exception." << endl;}cout << "Program continues after exception handling." << endl;return 0;
}

1.7.2运行结果示例:

1. 抛出整数类型异常:throw 42;

输出:

Caught an integer exception: 42
Program continues after exception handling.

2. 抛出浮点数类型异常:throw 3.14;

输出:

Caught a floating-point exception: 3.14
Program continues after exception handling.

3. 抛出 C 字符串类型异常:throw "An error occurred!";

输出:

Caught a C-string exception: An error occurred!
Program continues after exception handling.

4. 抛出 C++ 字符串类型异常:throw string("String object error");

输出:

Caught a string object exception: String object error
Program continues after exception handling.
5. 抛出标准库逻辑错误异常:throw logic_error("Logic error");

输出:

Caught logic_error: Logic error
Program continues after exception handling.

6. 抛出标准库运行时错误异常:throw runtime_error("Runtime error");

输出:

Caught runtime_error: Runtime error
Program continues after exception handling.

7. 抛出超出范围异常:throw out_of_range("Out of range error");

输出:

Caught out_of_range: Out of range error
Program continues after exception handling.

8. 抛出内存分配失败异常:throw bad_alloc();

输出:

Caught bad_alloc: std::bad_alloc
Program continues after exception handling.

9. 抛出自定义异常:throw MyException("Custom exception occurred!");

输出:

Caught custom exception: Custom exception occurred!
Program continues after exception handling.

10. 抛出未匹配的异常(如结构体或未列出的类型);
struct UnknownException {};
throw UnknownException();

输出:

Caught an unknown exception.
Program continues after exception handling.

1.7.3通用总结

  1. 对每种异常类型都有专门的 catch 块处理,并输出对应的内容。
  2. 如果异常类型不匹配,会进入通用的 catch(...) 块,确保程序不会因未捕获的异常而崩溃。

解析: 

  1. 逐个抛出不同类型的异常:

    1. 使用 throw 语句抛出整数、浮点数、字符串、标准库异常、自定义异常等。
  2. 多个 catch 块:

    1. 每个 catch 块捕获一种特定类型的异常。
    2. 使用 catch(...) 捕获所有未明确处理的异常。
  3. 自定义异常:

    1. 定义了一个 MyException 类,用于抛出和捕获自定义的错误。

二、用命名空间避免同名冲突


1. 什么是同名冲突?

1.1 同名冲突现象

在大型项目中,不同的模块或库可能会定义相同名字的变量、函数或类。这会导致程序不知道该调用哪一个。例如:

#include <iostream>
using namespace std;void print() {cout << "Global print function" << endl;
}namespace ModuleA {void print() {cout << "ModuleA's print function" << endl;}
}int main() {print();  // 问题:调用的是全局的 print 还是 ModuleA 的 print?return 0;
}
/*
输出:
Global print function
*/

这种情况下,同名的 print 函数可能引发歧义,导致意外的错误行为。


2. 什么是命名空间(namespace)?

2.1 定义

命名空间是 C++ 提供的一种机制,用来组织代码,解决名字冲突问题。
通过命名空间,程序员可以为变量、函数或类添加“所属空间”的限定,避免与其他模块中的名字冲突。

2.2 语法格式

namespace [命名空间的名字]{// 定义变量、函数、类
}
  • namespace_name 是命名空间的名字。
  • 命名空间的成员通过 namespace_name::member 访问。

3. 使用命名空间解决名字冲突

3.1 基本使用

将同名的函数或变量放入不同的命名空间,可以解决名字冲突问题:

#include <iostream>
using namespace std;namespace ModuleA {void print() {cout << "ModuleA's print function" << endl;}
}namespace ModuleB {void print() {cout << "ModuleB's print function" << endl;}
}int main() {ModuleA::print();  // 调用 ModuleA 的 print 函数ModuleB::print();  // 调用 ModuleB 的 print 函数return 0;
}
/*
输出:
ModuleA's print function 
ModuleB's print function
*/

解释:

  • print() 函数分别放在 ModuleAModuleB 命名空间中。
  • 通过 ModuleA::print()ModuleB::print() 调用,避免了名字冲突。

3.2 嵌套命名空间

命名空间可以嵌套使用,用于组织更复杂的代码:

#include <iostream>
using namespace std;namespace Outer {namespace Inner {void print() {cout << "Inner namespace print function" << endl;}}
}int main() {Outer::Inner::print();  // 调用嵌套命名空间中的函数return 0;
}
/*
输出:
Inner namespace print function
*/

注意:

  • 嵌套命名空间使代码结构更清晰,但调用成员时需要完整的命名空间路径。

4. 使用命名空间中的成员

4.1 使用 using 声明

通过 using namespace 声明,可以简化命名空间成员的调用:

#include <iostream>
using namespace std;namespace ModuleA {void print() {cout << "ModuleA's print function" << endl;}
}int main() {using namespace ModuleA;  // 引入 ModuleA 命名空间print();  // 直接调用 ModuleA 的 print 函数return 0;
}
/*
输出:
ModuleA's print function
*/

4.2 注意点

  1. 如果多个命名空间中有同名成员,不能直接使用 using namespace,需要明确调用:

    using namespace ModuleA;
    using namespace ModuleB;
    print();  // 错误:不明确调用哪个命名空间的 print
    
  2. 可以使用 using 声明单个成员:

    using ModuleA::print;  // 只引入 ModuleA 的 print 函数
    print();
    

5. 无命名空间的情况

5.1.问题

在没有命名空间的情况下,同名冲突会导致程序错误。例如:

#include <iostream>
using namespace std;void print() {cout << "Global print function" << endl;
}void print() {  // 重复定义cout << "Duplicate print function" << endl;
}int main() {print();  // 错误:重复定义导致编译错误return 0;
}

5.2.解决

将函数放入不同的命名空间即可避免冲突。


6. 标准命名空间 std

6.1 定义

C++ 标准库中的所有内容都定义在命名空间 std 中,例如 coutcinstring 等。

6.2使用方法

  • 通过 std:: 使用标准库成员:

    std::cout << "Hello, World!" << std::endl;
    
  • 或者引入 std 命名空间:

    using namespace std;
    cout << "Hello, World!" << endl;
    

6.3注意:

  • 在大型项目中,避免使用 using namespace std;,因为可能会与用户定义的名字冲突。

7. 总结

  1. 同名冲突:

    • 不同模块可能定义相同名字的变量、函数或类,导致冲突。
  2. 命名空间:

    • 通过 namespace 将代码分组,解决名字冲突。
    • 成员访问语法:namespace_name::member
  3. using 的使用:

    • 使用 using namespace 简化命名空间成员的调用,但要注意避免歧义。
  4. 标准命名空间:

    • std 是 C++ 标准库的命名空间,包含 coutcin 等标准成员。


三、总结

1.异常处理

  1. 异常处理通过 try-catch 机制捕获和处理异常,防止程序崩溃。
  2. 使用 throw 抛出异常,catch 捕获异常。
  3. 可自定义异常类,用于处理复杂错误。

2.命名空间

  1. 命名空间用于组织代码,避免命名冲突。
  2. 使用 namespace_name::identifier 访问命名空间中的成员。
  3. 可以使用 using namespace 简化调用。

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

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

相关文章

博客MDX渲染方案

MDX渲染方案 Link 本文不由AI生成,原创,转载请注明 当个人博客网站或是独立网站有博客页时,通过渲染mdx文件是一种效率比较高的方式生成博客文章的一种方式 MDX渲染方案 我之前是通过typora直接导出html文件,这种纯静态页面 缺点:太繁琐优点:可以自己选不同的主题,成本…

VScode MAC按任意键关闭终端 想要访问桌面文件

说明 最近配置MAC上CPP的运行环境&#xff0c;在安装必要的CPP插件后&#xff0c;配置launch和task等json文件后&#xff0c;点击运行三角形&#xff0c;每次都会跳出main想要访问桌面上的文件。并且输出也是在调试控制台&#xff0c;非常逆天。 尝试 尝试1:尽管我尝试将ta…

注意力机制+时空特征融合!组合模型集成学习预测!LSTM-Attention-Adaboost多变量时序预测

注意力机制时空特征融合&#xff01;组合模型集成学习预测&#xff01;LSTM-Attention-Adaboost多变量时序预测 目录 注意力机制时空特征融合&#xff01;组合模型集成学习预测&#xff01;LSTM-Attention-Adaboost多变量时序预测效果一览基本介绍程序设计参考资料 效果一览 基…

29.在Vue 3中使用OpenLayers读取WKB数据并显示图形

在Web开发中&#xff0c;地理信息系统&#xff08;GIS&#xff09;应用越来越重要&#xff0c;尤其是在地图展示和空间数据分析的场景中。OpenLayers作为一个强大的开源JavaScript库&#xff0c;为开发者提供了丰富的地图展示和空间数据处理能力。在本篇文章中&#xff0c;我将…

qt 设置系统缩放为150%,导致的文字和界面的问题

1 当我们设置好布局后&#xff0c;在100%的设置里面都是正常的&#xff0c;但是当我们修改缩放为150%后&#xff0c;字体图标&#xff0c;界面大小就出现问题了&#xff0c;这就需要我们设置一些参数。 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);QCoreAppl…

3个关于协程的题目

题目1&#xff1a; 题目1&#xff1a;启动2个协程&#xff0c;1个管道&#xff0c;每隔1秒交替输出1次1-10和a-j。 预期效果&#xff1a; 实现方式&#xff1a; package mainimport ("fmt""sync""time" )var ch make(chan struct{}, 1) var wg…

基于ESP32的桌面小屏幕实战[4]:硬件设计之PCB Layout

1. PCB Layout 步骤 生成PCB 确定PCB layout规范 绘制板框尺寸 布局 布局规范&#xff1a; 按电气性能合理分区&#xff0c;一般分为&#xff1a;数字电路区&#xff08;即怕干扰、又产生干扰&#xff09;、模拟电路区(怕干扰)、功率驱动区&#xff08;干扰源&#xff09;&a…

(六)科研技能-论文写作中的常用单词和句式

针对论文写作过程&#xff0c;会用到很多单词及短语。为了文章书写的规范&#xff0c;需要总结一些常用的单词、短语以及一些句式&#xff0c;因此进行了简单的总结以及梳理。后续会根据情况适时更新对应的内容。 一、常用单词、短语 关于&#xff1a;with respect to 更具体地…

无限次使用 cursor pro

github地址 cursor-vip 使用方式 在 MacOS/Linux 中&#xff0c;请打开终端&#xff1b; 在 Windows 中&#xff0c;请打开 Git Bash。 然后执行以下命令来安装&#xff1a; 部分电脑可能会误报毒&#xff0c;需要关闭杀毒软件/电脑管家/安全防护再进行 方式1&#xff1a;通过…

【Email】基于SpringBoot3.4.x集成发送邮件功能

【Email】基于SpringBoot3.4.x集成发送邮件功能 摘要本地开发环境说明pom.xml启动类application.yaml写一个邮件模板定义模板引擎工具类定义一个邮件发送对象封装一个邮件发送器单元测试邮件模板单元测试发送邮件单元测试 邮件效果参考资料 摘要 在业务系统开发过程中&#xf…

hoppscotch VS postman

下载&#xff1a;https://hoppscotch.com/download 使用&#xff1a;

使用LSTM神经网络对股票日线行情进行回归训练(Pytorch版)

版权声明&#xff1a;本文为博主原创文章&#xff0c;如需转载请贴上原博文链接&#xff1a;使用LSTM神经网络对股票日线行情进行回归训练&#xff08;Pytorch版&#xff09;-CSDN博客 前言&#xff1a;近期在尝试使用lstm对股票日线数据进行拟合&#xff0c;初见成型但是效果不…

Web项目图片视频加载缓慢/首屏加载白屏

Web项目图片视频加载缓慢/首屏加载白屏 文章目录 Web项目图片视频加载缓慢/首屏加载白屏一、原因二、 解决方案2.1、 图片和视频的优化2.1.1、压缩图片或视频2.1.2、 选择合适的图片或视频格式2.1.3、 使用图片或视频 CDN 加速2.1.4、Nginx中开启gzip 三、压缩工具推荐 一、原因…

MATLAB选取向量中最大的若干个值个值,并返回所在位置的函数

在 MATLAB 中&#xff0c;可以使用 maxk 函数来选取向量中最大的 ( k ) 个值&#xff0c;并返回它们的索引位置。maxk 函数非常方便&#xff0c;适用于需要获取前几个最大值的情形。 文章目录 语法 示例输出结果总结 语法 [M, I] maxk(A, k)A 是输入向量。k 是要选择的最大值…

PDFMathTranslate,PDF多语言翻译,批量处理,学术论文,双语对照(WIN/MAC)

分享一个非常实用的PDF文档翻译项目——PDFMathTranslate。作为一个经常逛GitHub的开发者&#xff0c;我总喜欢翻看各种项目附带的论文&#xff0c;虽然大多时候是瞎研究&#xff0c;但却乐在其中。该项目能够完美保留公式、图表、目录和注释&#xff0c;对于需要阅读外文文献的…

Mvc、Springmvc框架

一.Mvc&#xff1a; 1.概念&#xff1a; MVC它是一种设计理念。把程序按照指定的结构来划分: Model模型 、View视图 、Controller控制层&#xff1b; 结构图&#xff1a; 二.Springmvc: 1.概念&#xff1a; springmvc框架它是spring框架的一个分支。它是按照mvc架构思想设计…

item2 for macos

安装Item2 brew install iterm2 查看终端类型 cat /etc/shells Mac OS X 10.15 已经将默认的shell从Bash换成了zsh&#xff0c;所以不用安装&#xff0c;10.15以前的可以使用下面的命令进行安装 brew install zsh 安装Oh My ZSH # curl sh -c "$(curl -fsSL https://ra…

PyTorch基本使用-自动微分模块

学习目的&#xff1a;掌握自动微分模块的使用 训练神经网络时&#xff0c;最常用的算法就是反向传播。在该算法中&#xff0c;参数&#xff08;模型权重&#xff09;会根据损失函数关于对应参数的梯度进行调整。为了计算这些梯度&#xff0c;PyTorch 内置了名为 torch.autogra…

使用rust语言创建python模块(pyo3+maturin)

1. 首先使用conda创建python虚拟环境&#xff08;已创建的可省略&#xff09; >conda create --prefixE:\python_envs\rust_python python3.11 2. 激活python虚拟环境 conda activate rust_python 3. 安装maturin pip install maturin 4. 创建rust项目 >cd E:\py…

Linux 网络流量控制 - 实现概述

摘要 Linux 提供了一整套丰富的流量控制(traffic control)功能。本文档概述了相应的内核代码设计&#xff0c;描述了其结构&#xff0c;并通过描述一种新的排队策略来说明新元素的添加。 1 引言 最近的Linux内核提供了多种流量控制功能。Alexey Kuznetsov&#xff08;kuznet…