diff --git a/inheritance.html b/inheritance.html new file mode 100644 index 00000000..138d58a9 --- /dev/null +++ b/inheritance.html @@ -0,0 +1,164 @@ + +
Inheritance
+ + Py_cpp extension classes support single and multiple-inheritance in + Python, just like regular Python classes. You can mix built-in Python + classes with py_cpp extension classes in a derived class' tuple of + bases. Whenever a py_cpp extension class is among the bases for a new + class in Python, the result is an extension class: +
++ ++>>> class MyPythonClass: +... def f(): return 'MyPythonClass.f()' +... +>>> import my_extension_module +>>> class Derived(my_extension_module.MyExtensionClass, MyPythonClass): +... '''This is an extension class''' +... pass +... +>>> x = Derived() +>>> x.f() +'MyPythonClass.f()' +>>> x.g() +'MyExtensionClass.g()' ++
+ Py_cpp also allows us to represent C++ inheritance relationships so that + wrapped derived classes may be passed where values, pointers, or + references to a base class are expected as arguments: + +
++ ++#include+// for std::auto_ptr<> + +struct Base +{ + virtual ~Base() {} + virtual const char* name() const { return "Base"; } +}; + +struct Derived +{ + Derived() : x(-1) {} + virtual const char* name() const { return "Derived"; } + int x; +}; + +std::auto_ptr base_factory() { + return std::auto_ptr (new Derived); +} + +const char* get_name(const Base& b) { + return b.name(); +} + +int get_derived_x(const Derived& d) { + return d.x; +} +
+#include <py_cpp/class_wrapper.h> +extern "C" +#ifdef _WIN32 +__declspec(dllexport) +#endif +void initmy_module() +{ + try + { + py::Module my_module("my_module"); + + py::ClassWrapper<Base> base_class(my_module, "Base"); + base_class.def(py::Constructor<void>()); + + py::ClassWrapper<Derived> derived_class(my_module, "Derived"); + derived_class.def(py::Constructor<void>()); + // This establishes the inheritance relationship between Base and Derived + derived_class.declare_base(base_class); + + my_module.def(base_factory, "base_factory"); + my_module.def(get_name, "get_name"); + my_module.def(get_derived_x, "get_derived_x"); + } + catch(...) + { + py::handle_exception(); // Deal with the exception for Python + } +} +
+ Then, in Python: +
++ ++>>> from my_module import * +>>> base = Base() +>>> derived = Derived() +>>> get_name(base) +'Base' +>>> # objects of wrapped class Derived may be passed where Base is expected +>>> get_name(derived) +'Derived' +>>> # objects of wrapped class Derived can be passed where Derived is +>>> # expected but where type information has been lost. +>>> get_derived_x(base_factory()) +-1 ++
+ If for some reason your base class has no virtual functions but you still want
+ to represent the inheritance relationship between base and derived classes,
+ pass the special symbol py::without_downcast as the 2nd parameter
+ to declare_base:
+
+
+
+struct Base2 {};
+struct Derived2 { int f(); };
+
+ ...
+ py::ClassWrapper<Base> base2_class(my_module, "Base2");
+ base2_class.def(py::Constructor<void>());
+
+ py::ClassWrapper<Derived2> derived2_class(my_module, "Derived2");
+ derived2_class.def(py::Constructor<void>());
+ derived_class.declare_base(base_class, py::without_downcast);
+
+
+
+This approach will allow Derived2 objects to be passed where
+ Base2 is expected, but does not attempt to implicitly convert (downcast)
+ smart-pointers to Base2 into Derived2 pointers,
+ references, or values.
+
+
+ Previous: Function Overloading + Next: Special Method Names + Up: Top +
+ © Copyright David Abrahams 2000. Permission to copy, use, modify, + sell and distribute this document is granted provided this copyright + notice appears in all copies. This document is provided "as is" without + express or implied warranty, and with no claim as to its suitability + for any purpose. +
+ Updated: Oct 30, 2000 +