首页 > 解决方案 > C++ 自定义异常类

问题描述

我正在制作一个程序,并决定制作自己的例外,所以我编写了以下仅标头文件:

#ifndef ARGUMENT_EXCEPTIONS
#define ARGUMENT_EXCEPTIONS

#include <exception>


namespace AAerr {

    class ArgumentException : public std::exception {
    private:
        const char* msg;
        static constexpr char* funcName = (char*)"ArgumentException";
    public:
        ArgumentException(const char* msg_) {
            msg = msg_;
        }

        const char* getMessage() {
            return msg;
        }

        virtual const char* what() const throw() {
            return funcName;
        }
    };


    class WrongReturnType : public ArgumentException {
    private:
        const char* msg = "Wrong Type";
        char requestedType;
        char ofType;
        static constexpr char* funcName = (char*)"WrongReturnType";
    public:
        WrongReturnType(const char requested, const char is) : ArgumentException(msg) {
            requestedType = requested;
            ofType = is;
        }


        char get_requested_type() {
            return requestedType;
        }


        char get_of_type() {
            return ofType;
        }

        virtual const char* what() {
            return funcName;
        }
    };

}

#endif // ARGUMENT_EXCEPTIONS

当我试图在我的程序中抛出并捕获其中一个时,它从未捕获到任何东西:

#include "exception_header_file.hpp" // the name of the header file
#include <iostream>

int main() {
    try {
        throw AAerr::ArgumentException("TEST");
    } catch (AAerr::ArgumentException& exc) {
        std::cout << "CAUGHT EXCEPTION" << std::endl; // never executed
    }
}

然后我制作了第二个文件(只是为了找出问题所在):

#include <iostream>

#include <exception>

namespace AAerr {

    class Exc : public std::exception {
        private:
            const char* msg;
            static constexpr char* funcName = (char*)"TEST FUNC";
        public:
            Exc(const char* msg_) {
                msg = msg_;
            }

            const char* getMessage() {
                return msg;
            }

            virtual const char* what() {
                return funcName;
            }
    };

    class Exc2 : public Exc {
        private:
            int line;
            static constexpr char* funcName = (char*)"FUNCTION";
        public:
            Exc2(const char* msg_, int line_) : Exc(msg_) {line = line_;}
            virtual const char* what() {
                return funcName;
            }
    };
};

int main() {
    try {
        throw Exc2("TEST", 5);
    } catch (AAerr::Exc& exc) {
        std::cout << "CAUGHT EXCEPTION" << std::endl; // works fine
    }
}

有人可以帮我找出问题所在吗??我找不到这两个之间的任何区别。

编译器:g++(gcc) 平台:ubuntu(linux)

编辑: 我设法解决了这个问题。

它在链接器(ld)上。

我更改了我的 Makefile 来构建整个项目,而不是制作然后链接所有内容。

我的意思是,我做了:

build:
    g++ program_part1.cpp program_part2.cpp program_part3.cpp -o example.elf

代替:

build: part1.o part2.o part3.o
    g++ part1.o part2.o part3.o -o output.elf

part1.o: program_part1.cpp program_part1.hpp
    g++ -c program_part1.cpp -o part1.o

...
...

标签: c++exceptiontry-catch

解决方案


我怀疑问题出在“主程序”中,请参阅其他答案中的 OP 评论:

是的,我试过了,结果是一样的。它在我的主程序上不起作用,但在我拥有的测试程序上运行良好 – user898238409

如果“主程序”正在使用动态库并且异常被定义为“仅标题”,这可能导致该类多次生成 RTTI(运行时类型信息)的情况。每个包含一个包含此头文件的动态库和主要可执行文件。

例如,这可以是这样的:

  1. 动态库在异常时使用为该库生成的 RTTI 创建类的实例,AAerr::ArgumentException并将其作为异常抛出。
  2. 主要可执行文件正在尝试使用为该可执行文件构建的 RTTI 捕获该异常。

由于这两个 RTTI 彼此不匹配,因此 catch 语句无法注意到引发了预期的异常。

正确的解决方法是删除“仅标题”异常,因此所有虚拟方法都应在 cpp 文件中定义。这将导致与特定库的明确关联。因此,只有一个 RTTI 用于ArgumentExceptionWrongReturnType


推荐阅读