C++ 自定义异常 类
C++ Custom Exception classes
我正在制作一个程序并决定自己做例外,所以我写了以下 header-only 文件:
#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
...
...
您是否尝试捕获 std::exception 而不是异常 class?
像这样:
try{
throw AAerr::Argument exception("Test");
} catch (std::exception exc) {
std::cout << "HEY" << std::endl;
}
我怀疑问题出在“主程序”中,请参阅其他答案中的 OP 评论:
yeah i tried and it's the same thing. it doesn't work on my main program, but works fine on the testing program i have – user898238409
如果“主程序”正在使用动态库并且异常被定义为“仅header”,这可能会导致为此[生成 RTTI(运行 时间类型信息)的情况=30=] 多次。动态库和主要可执行文件各包含一个,其中包含此 header 文件。
例如可以这样:
- 动态库在异常时使用为该库生成的 RTTI 创建 class
AAerr::ArgumentException
的实例,并将其作为异常抛出。
- 主可执行文件正在尝试使用为该可执行文件构建的 RTTI 捕获该异常。
由于这两个 RTTI 彼此不匹配,因此 catch 语句无法注意到预期的异常被抛出。
正确的解决方法是删除“仅 header”异常,因此所有虚拟方法都应在 cpp 文件中定义。这将导致与特定库的明确关联。因此,ArgumentException
和 WrongReturnType
.
将只有一个 RTTI。
我正在制作一个程序并决定自己做例外,所以我写了以下 header-only 文件:
#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
...
...
您是否尝试捕获 std::exception 而不是异常 class?
像这样:
try{
throw AAerr::Argument exception("Test");
} catch (std::exception exc) {
std::cout << "HEY" << std::endl;
}
我怀疑问题出在“主程序”中,请参阅其他答案中的 OP 评论:
yeah i tried and it's the same thing. it doesn't work on my main program, but works fine on the testing program i have – user898238409
如果“主程序”正在使用动态库并且异常被定义为“仅header”,这可能会导致为此[生成 RTTI(运行 时间类型信息)的情况=30=] 多次。动态库和主要可执行文件各包含一个,其中包含此 header 文件。
例如可以这样:
- 动态库在异常时使用为该库生成的 RTTI 创建 class
AAerr::ArgumentException
的实例,并将其作为异常抛出。 - 主可执行文件正在尝试使用为该可执行文件构建的 RTTI 捕获该异常。
由于这两个 RTTI 彼此不匹配,因此 catch 语句无法注意到预期的异常被抛出。
正确的解决方法是删除“仅 header”异常,因此所有虚拟方法都应在 cpp 文件中定义。这将导致与特定库的明确关联。因此,ArgumentException
和 WrongReturnType
.