c++ - 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
...
...
解决方案
我怀疑问题出在“主程序”中,请参阅其他答案中的 OP 评论:
是的,我试过了,结果是一样的。它在我的主程序上不起作用,但在我拥有的测试程序上运行良好 – user898238409
如果“主程序”正在使用动态库并且异常被定义为“仅标题”,这可能导致该类多次生成 RTTI(运行时类型信息)的情况。每个包含一个包含此头文件的动态库和主要可执行文件。
例如,这可以是这样的:
- 动态库在异常时使用为该库生成的 RTTI 创建类的实例,
AAerr::ArgumentException
并将其作为异常抛出。 - 主要可执行文件正在尝试使用为该可执行文件构建的 RTTI 捕获该异常。
由于这两个 RTTI 彼此不匹配,因此 catch 语句无法注意到引发了预期的异常。
正确的解决方法是删除“仅标题”异常,因此所有虚拟方法都应在 cpp 文件中定义。这将导致与特定库的明确关联。因此,只有一个 RTTI 用于ArgumentException
和WrongReturnType
。
推荐阅读
- python - 在 Python 中排除建筑物形状列表中的点
- amazon-web-services - 使用 cPanel 重定向到另一个(AWS)URL 时如何保留参数
- sql - 无法获得正确的解决方案 sql server 2005
- c++ - 使用临时文件处理大量数据
- ruby-on-rails - Rails 将一个对象批量转换为另一个对象
- python - 将数据附加到流
- scala - 检查 spark 数据框列中的正则表达式
- html - 如何增加这个博客的宽度?(主体和小部件的宽度)
- python - 如何解决存储大数组的文件(pickle 数据被截断)?
- android-studio - 如何检测新/删除指纹