你会改变这段代码中的任何内容吗?
class LocalPort {
public:
LocalPort(int portNumber) {
innerPort = new ACMEPort(portNumber);
}
void Open() {
try {
innerPort->Open();
}
catch (DeviceResponseException& e) {
throw PortDeviceFailure(e);
}
catch (ATM1212UnlockedException& e) {
throw PortDeviceFailure(e);
}
catch (GMXError& e) {
throw PortDeviceFailure(e);
}
}
private:
ACMEPort* innerPort;
};
/////////
try {
LocalPort* port = new LocalPort(12);
port->Open();
}
catch (bad_alloc& e) {
ReportError(e);
logger.Log("Wyjątek alokacji pamięci", e);
delete port;
}
catch (PortDeviceFailure& e) {
ReportError(e);
logger.Log(e.getMessage(), e);
delete port;
}
我尝试以上做的是让代码低于看起来更好。
try {
ACMEPort* port = new ACMEPort(12);
port->Open();
}
catch (bad_alloc& e) {
ReportPortError(e);
logger.Log("Wyjątek alokacji pamięci", e);
delete port;
}
catch (DeviceReponseException& e) {
ReportPortError(e);
logger.Log("Wyjątek odpowiedzi urządzenia", e);
delete port;
}
catch (ATM1212UnlockedException& e) {
ReportPortError(e);
logger.Log("Wyjątek odblokowania", e);
delete port;
}
catch (GMXError& e) {
ReportPortError(e);
logger.Log("Wyjątek odpowiedzi urządzenia");
delete port;
}
catch (...) {
ReportPortError(0);
logger.Log("Wyjątek nieznanego pochodzenia");
delete port;
}
我成功了吗?第一个比第二个好吗?你觉得怎么样?
答案 0 :(得分:7)
看起来你设计的异常类很糟糕。为什么不简单地将一个成员函数getMessage
添加到您的异常层次结构中(最好是在基类中,所有异常派生自 - std::exception
提供返回的方法what
错误信息)。这样,您可以简单地在一个语句中捕获所有异常,并以相同的方式处理它们。
class DeviceResponseException : public std::runtime_error {
public:
DeviceResponseException() : std::runtime_error("Some error message") {}
};
class ATM1212UnlockedException : public std::runtime_error {
public:
ATM1212UnlockedException() : std::runtime_error("Some other error message") {}
};
然后在您的代码中,您可以执行此操作:
try {
std::auto_ptr<ACMEPort> port(new ACMEPort(12));
port->Open();
}
catch( std::runtime_error & e) {
ReportPortError(e);
logger.Log(e.what(), e);
}
由于您的异常类都派生自std::runtime_error
,因此这个catch
- 子句会捕获它们。这没关系,因为所有情况下的处理都是一样的。如果您有需要特殊处理的特定例外,则添加其他catch
- 子句。
此外,您应该使用delete port
或std::auto_ptr
或类似的东西,而不是在异常处理程序中调用boost::scoped_ptr
。阅读RAII。
答案 1 :(得分:2)
是的,我会:
基本上,我认为你完全误解了应该如何使用例外。
您可以对代码进行的最佳单一更改是替换:
ACMEPort* port = new ACMEPort(12);
port->Open();
使用:
ACMEPort port(12);
port.Open();
和其他地方类似 - 捕获异常的需要随之消失。
答案 2 :(得分:0)
我将异常处理程序移到类中,让类处理错误而不是强制所有调用者处理它。这样你可以通过检查Open()的结果值来清理指针(如果你因为某些原因必须有一个指针):
class LocalPort {
public:
LocalPort(int portNumber) {
innerPort = new ACMEPort(portNumber);
}
bool Open() {
try {
innerPort->Open();
return true;
}
catch (DeviceResponseException& e) {
throw PortDeviceFailure(e);
}
catch (ATM1212UnlockedException& e) {
throw PortDeviceFailure(e);
}
catch (GMXError& e) {
throw PortDeviceFailure(e);
}
catch (bad_alloc& e) {
ReportError(e);
logger.Log("Wyjątek alokacji pamięci", e);
}
catch (PortDeviceFailure& e) {
ReportError(e);
logger.Log(e.getMessage(), e);
}
return false;
}
private:
ACMEPort* innerPort;
};
LocalPort* port = new LocalPort(12);
if (!port->Open()) {
delete port;
}