迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > C++ >

在 C++ 中抛出异常消息

作者:迹忆客 最近更新:2023/08/20 浏览次数:

本文将解释如何在 C++ 中使用变量消息引发异常。 异常抛出是转移程序控制以避免崩溃或溢出的过程。

它是通过在程序中可能出现问题的地方抛出异常来执行的。 C++ 中有几个异常处理关键字,但本文将介绍如何使用可变消息引发异常。


使用标准 C++ 异常抛出带有消息的异常 - 无效参数

该程序使用 C++ 标准异常中的无效参数异常来抛出带有可变消息的异常。

导入包

该程序使用两个导入包,stdexcept 用于包含标准 C++ 异常,iostream 用于输入和输出操作。

抛出异常的方法

该程序定义了一个函数来比较作为输入提供的两个数字,并在遇到负输入时引发异常情况。 这里使用标准异常 std::invalid_argument。

在此程序中,定义了一个比较方法,使用两个整数值 var_a 和 var_b 作为参数。 这使用 if 来检查负数(a、b 或两者),如果是则抛出异常。

if (var_a < 0 || var_b < 0) {
    throw std::invalid_argument("Negative value encountered");

Main 方法

main 方法使用 try-catch 异常关键字来抛出有效的异常。

异常处理是通过调用try块内的compare方法来执行的。 由于输入 (-1,3) 具有负数,try 块会将参数发送到 catch 块,catch 块会抛出带有变量消息的异常并打印该消息。

#include <stdexcept>
#include <iostream>

using namespace std;


int check_neg( int var_a, int var_b) {
    if (var_a < 0 || var_b < 0) {
        throw std::invalid_argument("Negative value encountered");
    }
    return 0;
}

int main() {
    try {
    compare( -1, 3 );
    }
    catch( const std::invalid_argument& e ) {
    std::cout<<"booh!";
    }
}

输出:

booh!
--------------------------------
Process exited after 0.006709 seconds with return value 0
Press any key to continue . . .

使用标准 C++ 异常 - 嵌套异常通过消息引发异常

异常可以相互嵌套,以连续显示多条异常抛出消息。 本节中的程序将错误消息包装在嵌套异常中,然后在每次出现时抛出带有变量消息的异常,并将它们一起显示。

导入包

该程序中使用的导入包是:

  • iostream
  • stdexcept
  • exception
  • string
  • fstream

成员方法 该程序具有三个成员函数:print_exception、open_file 和 run。

方法 print_exception:

它有两个公共参数 - std::exception& ex 用于捕获 std 异常,以及一个用零值初始化的整数变量 stage。 在该方法内部,第一行 std::cerr 用于打印一条错误消息,即 Encountered Exception:,但使用 std::string(level,'') 将其放置在嵌套级别上。

错误消息后跟 ex.what,其中 ex 是 std::exception 的对象,ex.what 将返回发生错误的解释字符串。

try 块使用 std::rethrow_if_nested(e) 抛出异常,但仅限于 std 对象 ex 派生自嵌套异常的情况(在本程序中就是这样做的)。

catch 块使用std 对象nestedException 再次递归调用自身,同时将stage 的值加1。catch(...) 方法捕获所有异常。

void print_exception(const std::exception& ex, int level =  0)
{
    std::cerr << std::string(level, ' ') << "Encountered Exception: " << ex.what() << '\n';
    try {
        std::rethrow_if_nested(ex);
    } catch(const std::exception& nestedException) {
        print_exception(nestedException, stage+1);
    } catch(...) {}
}

上面代码中发生的情况是,它尝试打印异常的解释字符串。 如果函数发现它是嵌套的,它会递归打印它所持有的异常的解释。

方法 open_file:

该函数有一个字符串参数 std::string& s,它创建一个 std::string 对象并向其传递一个别名 s。

try-catch 块尝试读取文件,在无法加载文件时捕获异常,并将其包装在嵌套函数中。

void open_file(const std::string& s)
{
    try {
        std::ifstream file(s);
        file.exceptions(std::ios_base::failbit);
    } catch(...) {
        std::throw_with_nested( std::runtime_error("Couldn't open " + s) );
    }
}

方法 run():

void run() 方法在 try 块内调用 open_file 方法。 catch(...) 块捕获通过 std::throw_with_nested 产生的所有异常。

它引发一个异常,该异常将 e 与当前正在处理的异常结合起来。

此时正在处理的异常成为外部异常,e 成为嵌套异常。 “run() failed”是打印的最终消息。

void run()
{
    try {
        open_file("nonexistent.file");
    } catch(...) {
        std::throw_with_nested( std::runtime_error("run() failed") );
    }
}

方法 int main():

main 方法在 try 块内调用 run() 函数,而在 catch 块内,程序调用 print_exception 方法,同时传递 e 作为参数。

它运行用可变消息抛出异常的函数,打印以嵌套格式捕获的异常,并在每个异常抛出时显示自定义消息。

int main()
{
    try {
        run();
    } catch(const std::exception& e) {
        print_exception(e);
    }
}

完整代码:

#include <iostream>
#include <stdexcept>
#include <exception>
#include <string>
#include <fstream>

void print_exception(const std::exception& ex, int stage =  0)
{
    std::cerr << std::string(stage, ' ') << "Encountered Exception: " << ex.what() << '\n';
    try {
        std::rethrow_if_nested(ex);
    } catch(const std::exception& nestedException) {
        print_exception(nestedException, stage+1);
    } catch(...) {}
}

void open_file(const std::string& s)
{
    try {
        std::ifstream file(s);
        file.exceptions(std::ios_base::failbit);
    } catch(...) {
        std::throw_with_nested( std::runtime_error("Couldn't open " + s) );
    }
}

void run()
{
    try {
        open_file("nonexistent.file");
    } catch(...) {
        std::throw_with_nested( std::runtime_error("run() failed") );
    }
}

int main()
{
    try {
        run();
    } catch(const std::exception& e) {
        print_exception(e);
    }
}

输出:

exception: run() failed
 exception: Couldn't open nonexistent.file
  exception: basic_ios::clear

--------------------------------
Process exited after 0.05326 seconds with return value 0
Press any key to continue . . .

在 C++ 中使用运行时错误通过消息引发异常

自定义类可用于抛出带有可变消息的异常,以及源文件的路径和抛出此错误的行。

该程序使用自定义类和宏,使用 std::runtime_error 在解释字符串中输出变量消息。

导入包

该程序需要四个导入包,分别是:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

Public 类

该程序使用构造函数类来抛出带有变量消息的异常,并在使用 std::runtime_error 调用公共构造函数时将该自定义消息显示为解释性字符串。

代码片段中的第一行创建一个类 my_exception 和一个新的 runtime_error 对象。 除此之外,还创建了一个具有全局作用域的字符串对象 msg,它将用于传递解释变量字符串。

构造函数类 my_exception 使用三个参数进行初始化:一个传递解释字符串的 std 字符串对象 arg、一个存储文件名的 char 数据类型的指针对象 *file 以及一个存储异常所在行的整型变量 line 被抛出。

使用 std::ostringstream 创建字符串输出对象,以便在调用该对象时显示输出。 最后,该对象存储在变量 msg 中。

析构函数 ~my_exception() 使用 return msg.c_str(); 将变量 msg 作为以 null 结尾的字符串返回。

class my_exception : public std::runtime_error {
    std::string msg;
public:
    my_exception(const std::string &arg, const char *file, int line) :
    std::runtime_error(arg) {
        std::ostringstream o;
        o << file << ":" << line << ": " << arg;
        msg = o.str();
    }
    ~my_exception() throw() {}
    const char *what() const throw() {
        return msg.c_str();
    }
};

宏和异常抛出

这里,使用 #define throw_line(arg) 定义了一个宏。 调用 throw_line() 将抛出 my_exception(arg, __FILE__, __LINE__)

方法 void f() 调用宏 throw_line 并传递消息 Oh no!。

#define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__);

void f() {
    throw_line("Oh no!");
}

Main 方法

main 方法将通过调用 try 块内的方法 f() 来抛出带有可变消息的异常。 这会将消息块传递给方法 my_exception。

在 catch 块内,创建了一个 runtime_error 对象 ex,它将使用 ex.what() 调用解释字符串。

当调用解释字符串时,ostream 对象在 my_exception 构造函数内被调用,并返回文件名和错误行以及变量消息。

int main() {
    try {
        f();
    }
    catch (const std::runtime_error &ex) {
        std::cout << ex.what() << std::endl;
    }
}

完整代码:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

class my_exception : public std::runtime_error {
    std::string msg;
public:
    my_exception(const std::string &arg, const char *file, int line) :
    std::runtime_error(arg) {
        std::ostringstream o;
        o << file << ":" << line << ": " << arg;
        msg = o.str();
    }
    ~my_exception() throw() {}
    const char *what() const throw() {
        return msg.c_str();
    }
};
#define throw_line(arg) throw my_exception(arg, __FILE__, __LINE__);

void f() {
    throw_line("Oh no!");
}

int main() {
    try {
        f();
    }
    catch (const std::runtime_error &ex) {
        std::cout << ex.what() << std::endl;
    }
}

输出:

D:\c++\std-exceptions\8.cpp:23: Oh no!

--------------------------------
Process exited after 0.006875 seconds with return value 0
Press any key to continue . . .

总结

本文介绍了使用可变消息引发异常并在引发异常时显示消息的各种方法。

希望本文能帮助您学习如何使用可变消息引发异常,并且您将能够在实际场景中使用它。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

Arduino 中停止循环

发布时间:2024/03/13 浏览次数:444 分类:C++

可以使用 exit(0),无限循环和 Sleep_n0m1 库在 Arduino 中停止循环。

Arduino 复位

发布时间:2024/03/13 浏览次数:315 分类:C++

可以通过使用复位按钮,Softwarereset 库和 Adafruit SleepyDog 库来复位 Arduino。

Arduino 的字符转换为整型

发布时间:2024/03/13 浏览次数:181 分类:C++

可以使用简单的方法 toInt()函数和 Serial.parseInt()函数将 char 转换为 int。

Arduino 串口打印多个变量

发布时间:2024/03/13 浏览次数:381 分类:C++

可以使用 Serial.print()和 Serial.println()函数在串口监视器上显示变量值。

Arduino if 语句

发布时间:2024/03/13 浏览次数:123 分类:C++

可以使用 if 语句检查 Arduino 中的不同条件。

Arduino ICSP

发布时间:2024/03/13 浏览次数:214 分类:C++

ICSP 引脚用于两个 Arduino 之间的通信以及对 Arduino 引导加载程序进行编程。

使用 C++ 编程 Arduino

发布时间:2024/03/13 浏览次数:127 分类:C++

本教程将讨论使用 Arduino IDE 在 C++ 中对 Arduino 进行编程。

Arduino 中的子程序

发布时间:2024/03/13 浏览次数:168 分类:C++

可以通过在 Arduino 中声明函数来处理子程序。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便