从基类调用最终类构造函数
Invoke final class constructor from base class
我有一个异常类,如下所示:
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" );
由于 TypeError : Exception 和 Exception::wrap 是公共的,我可以为wrap创建一个可选的第二个参数:
static void wrap( int condition, string err="default-err" ) {
if( condition == -1 )
throw FinalClassConstructor{ err }; // <-- how to do this?
}
。但是我该如何为刚刚命中 ::wrap 的最终类调用构造函数呢?
你试图做的事情违背了多个 SOLID 原则。你也使你的基类与它的后代紧密耦合(!)。你绝对不希望这样。它应该不知道谁继承了。
要做到这一点,请覆盖子类中的 Wrap 函数,它们基本上在其中抛出自己。在你的代码中,你将使用StandardError.Wrap(...
但老实说,我只会将异常留在代码中。
(无论条件如何 ->抛出异常)在代码中都很好,并且比使用静态方法的另一个异常中的异常更具可读性。
当您不应该再重构它时,就是这种情况。
相关文章:
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 参数包构造函数在类模板中隐藏用户定义的转换
- 具有已删除移动和复制构造函数的类的就地构造
- 创建一个没有复制构造函数的类的 std::vector 的 std::vector
- C++构造函数和类?
- 在 C++ 中,默认情况下构造函数为类的数据成员提供的值是多少?
- 如何在其他类中使用参数化构造函数制作类的对象?
- 具有值包装器的可变参数模板构造函数的类构造函数优先级
- 如何使用私有构造函数对类进行单元测试?
- C++虚拟函数:基类函数是调用的,而不是派生的
- c++17在编译时将带有已删除复制构造函数的类添加到std::vector
- 从作为模板参数传递给构造函数的类继承,或者从它们继承
- 继承的构造函数忽略类内初始化
- 模板和隐式构造函数的类定义之外的友元声明
- 具有字符串文本构造函数的类不适用于 const 引用初始化
- 为什么具有私有构造函数的类不阻止从此类继承?如何控制哪些类可以从某个基继承?
- 具有多个非默认构造函数基的Singleton派生类
- 调用基默认构造函数模板类
- 当基类未指定构造函数时,如何使用仅具有带参数的构造函数的类派生基类?
- 构造所有基类不需要默认生成的构造函数