最近更新于 2023-03-10 07:39

环境

Debian 11(arm64)

编译器 g++ 10.2.1;编译标准 C++20;参数:-std=c++20 -no-pie -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Werror=format-security -Wextra -pedantic -Wimplicit-fallthrough -Wsequence-point -Wswitch-unreachable -Wswitch-enum -Wstringop-truncation -Wbool-compare -Wtautological-compare -Wfloat-equal -Wshadow=global -Wpointer-arith -Wpointer-compare -Wcast-align -Wcast-qual -Wwrite-strings -Wdangling-else -Wlogical-op -Wconversion -g -O0

抛出异常消息

#include <iostream>

int main()
{
    try
    {
        int x = 10;
        int y = 0;

        if (y == 0)
        {
            throw "除数为 0";
        }

        std::cout << x / y << std::endl;
    }
    catch (const char *msg)
    {
        std::cerr << "捕获到异常:" << msg << std::endl;
    }
    catch (...)
    {
        std::cerr << "未知异常" << std::endl;
    }
}

file

标准异常

标准异常类

std::bad_alloc:当动态内存分配失败时,会抛出该异常。
std::bad_cast:当使用dynamic_cast转换失败时,会抛出该异常。
std::logic_error:表示程序逻辑错误,包括以下几个子类:
    std::invalid_argument:当传递给函数的参数无效时,会抛出该异常。
    std::domain_error:当数学函数的参数超出定义域时,会抛出该异常。
    std::length_error:当试图创建一个超出允许范围的字符串或容器时,会抛出该异常。
    std::out_of_range:当索引超出有效范围时,会抛出该异常。
std::runtime_error:表示运行时错误,包括以下几个子类:
    std::overflow_error:当计算结果超出了数值类型的范围时,会抛出该异常。
    std::underflow_error:当计算结果小于数值类型的最小值时,会抛出该异常。
    std::range_error:当某个计算结果超出了数值类型的可表示范围时,会抛出该异常。
    std::system_error:表示底层操作系统或库函数返回错误代码时,会抛出该异常。
#include <iostream>
#include <exception>

int main()
{
    try
    {
        int x = 10;
        int y = 0;

        if (y == 0)
        {
            throw std::runtime_error("除数为 0");
        }

        std::cout << x / y << std::endl;
    }
    catch (const std::exception &e)
    {
        std::cerr << "捕获到异常:" << e.what() << std::endl;
    }
}

file

自定义异常类

自定义异常

#include <iostream>
#include <exception>

class MyException : public std::exception
{
    public:
        virtual const char *what() const noexcept
        {
            return "这是一个自定义异常";
        }
};

int main()
{
    try
    {
        throw MyException();
    }
    catch (const std::exception &e)
    {
        std::cerr << "捕获到异常:" << e.what() << std::endl;
    }
}

file

自定义异常虚析构的使用

这里假定一个情景,抛出自定义的异常对象后,首先打开(或创建)一个错误日志文件,并往里面追加错误信息,同时将错误信息返回给捕获错误处,自定义异常对象寿命终止,虚析构检查错误日志文件是否关闭,没有关闭就关闭文件。

#include <iostream>
#include <fstream>
#include <exception>

class MyException : public std::exception
{
    public:
        MyException(const char *message, const char *file) : msg(message), filename(file)
        {
            log();
        }

        virtual ~MyException() noexcept
        {
            if (logFile.is_open())
            {
                logFile.close();
            }
        }

        virtual const char *what() const noexcept
        {
            return msg.c_str();
        }

        void log()
        {
            logFile.open(filename, std::ios::out | std::ios::app);
            if (logFile.is_open())
            {
                logFile << msg << std::endl;
                logFile.close();
            }
        }

    private:
        std::string msg;
        std::string filename;
        std::ofstream logFile;
};

int main() {
    try
    {
        throw MyException("出现 XXX 错误", "error.log");
    }
    catch (const std::exception &e)
    {
        std::cerr << "捕获到异常:" << e.what() << std::endl;
    }
}