迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > 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 . . .

总结

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

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

上一篇:C++ 中的 A Declaration Shadows a Parameter 错误

下一篇:没有了

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

本文地址:

相关文章

C++ 中的 A Declaration Shadows a Parameter 错误

发布时间:2023/08/21 浏览次数:188 分类:C++

每个对象或变量总是有一些边界、范围或作用域来访问其他类成员,例如由 C++ 中的访问说明符定义为 public、private 或 protected 的数据成员或成员函数。当我们在程序的特定范围或块中多次定义

C++ 中的错误 Error ID Returned 1 Exit Status

发布时间:2023/08/21 浏览次数:130 分类:C++

C++ [Error]: Id returned 1 exit status 不是常见错误。 这通常意味着程序崩溃了,并且在不查看堆栈跟踪的情况下很难确定原因。

C++ 中错误 Too Many Arguments to Function

发布时间:2023/08/21 浏览次数:177 分类:C++

我们在编写一段代码时会遇到很多错误。 解决错误是编程中最关键的部分之一。本文将讨论我们在 C++ 中遇到的一个错误:Too Many Arguments to Function。

处理 C++ 中的错误

发布时间:2023/08/21 浏览次数:197 分类:C++

本文讨论了 C++ 中的错误和异常处理。C++ 中的错误处理 C++ 程序中可能存在多种类型的错误。 有些错误需要向用户发出提示。

C++ 中错误 Function Returns the Address of a Local Variable

发布时间:2023/08/21 浏览次数:119 分类:C++

根据作用域,C 和 C++ 中的变量分为局部变量和全局变量。 虽然可以从程序的任何部分访问全局变量,但局部变量却不然。让我们讨论一下为什么会出现这个错误以及如何修复它。

C++ 错误 Invalid Conversion of Int* to Int

发布时间:2023/08/21 浏览次数:154 分类:C++

这个简短的教程将讨论错误消息 Invalid conversation of int* to int 。 首先,让我们回顾一下 C++ 中的指针。

C++ 中的错误 Solved: Expression Must Have Class Type

发布时间:2023/08/21 浏览次数:62 分类:C++

让我们看看为什么会发生这种情况以及如何解决。C++ 中错误 Solved: Expression Must Have Class Type 为了更好地理解问题陈述,请查看下面的代码。 在这里,我们有一个名为 Deserts 的类,其中包含函数

C++ 迷宫求解器

发布时间:2023/08/20 浏览次数:150 分类:C++

迷宫求解算法是计算机科学和人工智能中的经典问题。C++ 迷宫求解器 迷宫求解算法旨在通过仅在四个罗盘方向上移动来找到从起点到终点的最短路径。

C++ 的包管理器

发布时间:2023/08/20 浏览次数:93 分类:C++

复杂的软件在其系统中需要大量的依赖项。 像 Python 这样的编译语言有 pip 来管理它们的包,但我们很少听到 C/C++ 的包管理器。本文介绍如何安装和实现 C++ 的包管理器。VC Package (vcpkg) - C++ 的包

扫一扫阅读全部技术教程

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

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便