.. _constructors: Constructors ============ In the :ref:`tutorial` we touched upon how to wrap C++ constructors. Now let's go into more depth. C++ supports several types of constructors, including: * Default constructors * Copy constructors * Move constructors * Custom constructors In addition, unlike a Ruby class, a C++ class may include many constructors. .. _example: Example ------- For example, consider this simplified version of `OpenCV's Mat `_ class: .. code-block:: cpp class Mat { public: Mat(); Mat(int rows, int cols, int type); Mat(const std::vector& sizes, int type); Mat(const Mat& m); Mat(Mat&& m); } The Rice binding for the above example is: .. code-block:: cpp #include #include using namespace Rice; extern "C" void Init_Mat() { Data_Type rb_cMat = define_class("Mat") .define_constructor(Constructor()) .define_constructor(Constructor()) .define_constructor(Constructor&, int>()) .define_constructor(Constructor()) .define_constructor(Constructor()); } Notice that the Constructor template requires the full list of argument types needed by the constructor. For more information on how Rice decides which constructor to call, please see the :ref:`overloaded methods ` section. .. _default_constructor: Default Constructor ------------------- Most C++ classes include a default constructor that takes no arguments. These are mapped to Rice like this: .. code-block:: cpp define_constructor(Constructor()) This defines a constructor that takes no arguments. It can be invoked from Ruby using the following code: .. code-block:: ruby Mat.new Under the hood, the ``define_constructor`` call creates a new ``initialize`` method on the Ruby ``Mat`` class. The ``initialize`` method is responsible for creating a new C++ ``Mat`` instance and associating it with the wrapper Ruby object. Thus if you override the ``initialize`` method you MUST call ``super``: .. code-block:: ruby class Mat def initialize super # <--- You MUST call super first ...your code.. end end .. _custom_constructors: Custom Constructors ------------------- The ``Mat`` class defines two custom constructors: .. code-block:: cpp define_constructor(Constructor()) define_constructor(Constructor&, int>()) These are invoked from Ruby like this: .. code-block:: ruby Mat.new(1, 2, 3) vec = Std::Vector.new Mat.new(vec, 4) Similarly to default constructors, calling ``define_constructor`` will creates a new ``initialize`` method on the corresponding Ruby class. .. _copy_constructors: Copy Constructors ------------------- Most C++ classes include a copy constructor that takes one argument. These are mapped to Rice like this: .. code-block:: cpp define_constructor(Constructor()) Rice maps copy constructors to Ruby's ``clone`` and ``dup`` methods: .. code-block:: ruby mat1 = Mat.new(1, 2, 3) mat2 = mat1.dup mat3 = mat1.clone Under the hood, the ``define_constructor`` call creates a new ``initialize_copy`` method on the Ruby Mat class. The ``initialize_copy`` method is responsible for calling the C++ copy constructor and assigning the new C++ instance to the wrapper Ruby object. Thus if you override the ``initialize_copy`` method you MUST call ``super``: .. code-block:: ruby class Mat def initialize_copy super # <--- You MUST call super first ...your code.. end end .. _move_constructors: Move Constructors ------------------- Rice does not currently support move constructors. Of course, you can roll your own support as needed.