2014-11-26 3 views
0

에서 최종 클래스 생성자를 호출 : 난 그냥 추가 한다음과 같이 내가 예외 클래스가 기본 클래스

class ExtensionExceptionType; 
class Object; 

class Exception 
{ 
public: 
    explicit Exception() { } 

    Exception(      const std::string &reason) { PyErr_SetString(_Exc_RuntimeError(), reason.c_str()); } 
    Exception(PyObject* exception, const std::string &reason) { PyErr_SetString(exception,   reason.c_str()); } 

    Exception(PyObject* exception, Object& reason); 

    Exception(ExtensionExceptionType& exception, const std::string& reason); 
    Exception(ExtensionExceptionType& exception, Object&   reason); 

    void clear() { PyErr_Clear(); } // clear the error -- technically but not philosophically const 

    static Object err_type(); 
    static Object err_value(); 
    static Object err_trace(); 

    static Object err_stats(uint32_t i); // 0 1 2 for {type, value, trace} 

    static void wrap(int condition) { 
     if(condition == -1) 
      throw Exception{}; 
    } 
}; 

// Abstract 
class StandardError  : public Exception  { protected: explicit StandardError() {} }; 

class LookupError  : public StandardError { protected: explicit LookupError()  {} }; 
class ArithmeticError : public StandardError { protected: explicit ArithmeticError() {} }; 
class EnvironmentError : public StandardError { protected: explicit EnvironmentError() {} }; 

// Concrete (π) 

// e.g. 
// class TypeError: public StandardError 
// { 
// public: 
//  TypeError (const std::string& reason) 
//  : StandardError() 
//  { 
//   PyErr_SetString(Py::_Exc_TypeError(),reason.c_str()); 
//  } 
// }; 

#define CONCRETE(CLASS, BASE) \ 
class CLASS: public BASE \ 
    { \ 
    public: \ 
     CLASS (const std::string& reason) \ 
     { \ 
      std::cout << "(Exception.hxx) " #CLASS " from PyCXX (" << reason.c_str() << ") \n"; \ 
      PyErr_SetString(_Exc_##CLASS(), reason.c_str()); \ 
     } \ 
    }; 

// it appears that these classes are only for manually RAISING Python errors 
// i.e. Raising an exception in the Python runtime 
// because if I type something in to the Python console, I can make (e.g.) a KeyError occur, but these classes don't get hit. 

CONCRETE(TypeError,   StandardError ) 
CONCRETE(IndexError,   LookupError ) 
CONCRETE(AttributeError,  StandardError ) 
CONCRETE(NameError,   StandardError ) 
CONCRETE(RuntimeError,   StandardError ) 
CONCRETE(NotImplementedError, StandardError ) 
CONCRETE(SystemError,   StandardError ) 
CONCRETE(KeyError,    LookupError ) 
CONCRETE(ValueError,   StandardError ) 
CONCRETE(OverflowError,  ArithmeticError) 
CONCRETE(ZeroDivisionError, ArithmeticError) 
CONCRETE(FloatingPointError, ArithmeticError) 
CONCRETE(MemoryError,   StandardError ) 
CONCRETE(SystemExit,   StandardError ) 

:

static void wrap(int condition) { 
     if(condition == -1) 
      throw Exception{}; 
    } 

을 다른 곳에서의 많은 경우가 있었기 때문에 ... ..

:.들로 정돈 된

if(SomePythonFunc(...) == -1) throw Exception{}; 

... 의도하지만

Exception.wrap(SomePythonFunc(...)); // much nicer, I think 

,이 경우 :

if(SomePythonFunc(...) == -1) throw TypeError{ "foo" }; 

... 내가 동등한 포장을 수행하는 방법을 볼 수 없습니다.

즉, 쓰기 :

TypeError.wrap(SomePythonFunc(...), "foo"); 

형식 오류로 : 예외 및 예외 :: 랩 공개, 난 그냥 랩에 대한 선택적인 두 번째 매개 변수를 만들 수 있습니다

static void wrap(int condition, string err="default-err") { 
     if(condition == -1) 
      throw FinalClassConstructor{ err }; // <-- how to do this? 
    } 

을 ...하지만 어떻게 :: 랩이 막 히트 된 최종 클래스의 생성자를 호출합니까?

답변

2

여러 솔리드 원칙을 무시하십시오. 또한 하위 클래스와 기본 클래스를 단단히 결합합니다 (!). 당신은 확실히 그것을 원하지 않습니다. 상속 한 사람이 누구인지 알 필요가 없습니다.

정상적으로 처리하려면 자체적으로 던져 넣는 하위 클래스의 줄 바꾸기 기능을 재정의하십시오. 코드에서는 StandardError.Wrap (...

갈 것이다 그러나 솔직히 난 그냥 코드에서 예외를 떠날 것이다

(뭐든 조건 -.> 던져 예외) 코드에 완벽하게 괜찮 및 방법 정적 메서드를 사용하는 다른 예외 내에서 읽기보다 읽기 쉽습니다.

더 이상 리팩토링하지 않아야하는 경우입니다.

관련 문제