我继承了Python中的一些代码以转换为C++。 Python代码基于其他函数返回的错误代码引发异常。 Python代码使用称为errors(...)
的实用程序函数,该函数包含创建字典以将错误代码映射到异常。它返回异常的类型,并且调用代码使用其自己的消息将其实例化。
class BaseError(Exception):
pass
class Error1(BaseError):
pass
class Error2(BaseError):
pass
def errors(code):
errors_ = {
1: BaseError,
2: Error1,
3: Error2
}
try:
return errors_[code]
except KeyError:
return errors_[1]
def ReturnAnError():
# Oops an error!
return 2
try:
val = ReturnAnError()
if(val):
raise errors(val)('{} Failed'.format("Example Failed"))
except BaseError as ex:
print(ex)
我最初的想法是走一条简单的道路,将Python的errors(code)
函数重新定义为c++中的void errors(uint8_t code, const char * msg)
,然后做出一条选择语句,该语句本身将引发异常。是否存在更优雅或更简洁的解决方案来直接翻译此代码?特别是在C++中
raise errors(val)('{} Failed'.format("Example Failed"))
最直接的翻译是什么?
最佳答案
如果我直接用C++翻译您的代码:
#include <iostream>
#include <string>
#include <map>
class BaseError {
public:
BaseError(std::string s) : msg(s) {}
virtual ~BaseError() {} // useless because inherited classes do not have attribute to delete
friend std::ostream & operator<<(std::ostream & out, const BaseError & e) {
out << e.msg;
return out;
}
static BaseError * mk(std::string s) { return new BaseError(s); }
private:
std::string msg;
};
class Error1 : public BaseError {
public:
Error1(std::string s) : BaseError(s) {}
static BaseError * mk(std::string s) { return new Error1(s); }
};
class Error2 : public Error1 {
public:
Error2(std::string s) : Error1(s) {}
static BaseError * mk(std::string s) { return new Error2(s); }
};
typedef BaseError * (*fmk)(std::string);
fmk errors(int code)
{
const static std::map<int, fmk> error = {
{1, &BaseError::mk},
{2, &Error1::mk},
{3, &Error2::mk}
};
std::map<int, fmk>::const_iterator it = error.find(code);
return ((it == error.end()) ? error.find(1) : it)->second;
}
int ReturnAnError()
{
// Oops an error!
return 2;
}
int main()
{
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (BaseError * ex) {
std::cout << *ex << std::endl;
delete ex;
}
}
编译与执行:pi@raspberrypi:/tmp $ g++ c0.cc
pi@raspberrypi:/tmp $ ./a.out
blah blah
pi@raspberrypi:/tmp $
关于函数错误:std::map
std::map
中输入每个类的构造函数的地址,这就是为什么我对每个类使用静态操作mk的原因。std::map
,我定义了错误static
(和const
明确表示我不想对其进行修改),但这是一种优化,并非强制性的。为了能够打印类的实例,我重载了
operator<<
,无论如何不允许检查程序创建了Error1,甚至我将代码更改为: try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (Error2 * ex) {
std::cout << "err2" << *ex << std::endl;
delete ex;
}
catch (Error1 * ex) {
std::cout << "err1" << *ex << std::endl;
delete ex;
}
catch (BaseError * ex) {
std::cout << *ex << std::endl;
delete ex;
}
执行的代码将是catch (BaseError * ex) {...}
如果我做 : try {
int val = ReturnAnError();
if (val)
throw *(errors(val))("blah blah");
}
catch (Error2 & ex) {
std::cout << "err2" << ex << std::endl;
}
catch (Error1 & ex) {
std::cout << "err1" << ex << std::endl;
}
catch (BaseError & ex) {
std::cout << ex << std::endl;
}
再次执行的代码将是catch (BaseError & ex) {...}
(并且我创建了内存泄漏)。因此,在进行绘画时需要
virtual
操作来区分类,例如:#include <iostream>
#include <string>
#include <map>
class BaseError {
public:
BaseError(std::string s) : msg(s) {}
virtual ~BaseError() {} // useless because inherited classes do not have attribute to delete
virtual void print(std::ostream & out) const { out << msg; }
static BaseError * mk(std::string s) { return new BaseError(s); }
private:
std::string msg;
};
class Error1 : public BaseError {
public:
Error1(std::string s) : BaseError(s) {}
virtual void print(std::ostream & out) const {
out << "error1 ";
BaseError::print(out);
}
static BaseError * mk(std::string s) { return new Error1(s); }
};
class Error2 : public Error1 {
public:
Error2(std::string s) : Error1(s) {}
virtual void print(std::ostream & out) const {
out << "error2 ";
BaseError::print(out);
}
static BaseError * mk(std::string s) { return new Error2(s); }
};
typedef BaseError * (*fmk)(std::string);
fmk errors(int code)
{
const static std::map<int, fmk> error = {
{1, &BaseError::mk},
{2, &Error1::mk},
{3, &Error2::mk}
};
std::map<int, fmk>::const_iterator it = error.find(code);
return ((it == error.end()) ? error.find(1) : it)->second;
}
int ReturnAnError()
{
// Oops an error!
return 2;
}
int main()
{
try {
int val = ReturnAnError();
if (val)
throw (errors(val))("blah blah");
}
catch (BaseError * ex) {
ex->print(std::cout);
std::cout << std::endl;
delete ex;
}
}
编译与执行:pi@raspberrypi:/tmp $ g++ c.cc
pi@raspberrypi:/tmp $ ./a.out
error1 blah blah
pi@raspberrypi:/tmp $
Is there a more elegant or concise solution
坦率地说,这至少不够简洁,但是您的Python代码却不太好;-)
关于python - 将Python返回的类型转换为C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63251830/