Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You need to instantiate a factory function for each class you want to be able to build by this means. The following code shows you how to do so without having to recur to static members and by not writing by hand a number of different functions:</p> <pre><code>#include &lt;iostream&gt; #include &lt;map&gt; #include &lt;functional&gt; #include &lt;string&gt; #include &lt;memory&gt; struct Parent{ Parent(std::string){} }; struct Child1 : public Parent{ Child1(std::string d) : Parent(d){ std::cout &lt;&lt; "Child1 constructor: " &lt;&lt; d &lt;&lt; std::endl; } }; struct Child2 : public Parent{ Child2(std::string d) : Parent(d){ std::cout &lt;&lt; "Child2 constructor: " &lt;&lt; d &lt;&lt; std::endl; } }; template &lt;typename Product, typename Return, typename Parameter&gt; Return factory(const Parameter&amp; a){ return Return(new Product(a)); } std::map&lt;std::string, std::function&lt;Parent*(std::string)&gt; &gt; mrp; std::map&lt;std::string, std::function&lt;std::shared_ptr&lt;Parent&gt;(std::string)&gt; &gt; msp; int main(){ mrp["Child1"] = &amp;factory&lt;Child1, Parent*, std::string&gt;; mrp["Child2"] = &amp;factory&lt;Child2, Parent*, std::string&gt;; Parent* a = mrp["Child1"]("one"); delete a; std::unique_ptr&lt;Parent&gt; b(mrp["Child2"]("two")); msp["Child1"] = &amp;factory&lt;Child1, std::shared_ptr&lt;Parent&gt;, std::string&gt;; msp["Child2"] = &amp;factory&lt;Child2, std::shared_ptr&lt;Parent&gt;, std::string&gt;; msp["Child1"]("one"); msp["Child2"]("two"); } </code></pre> <p>try this code <a href="http://coliru.stacked-crooked.com/view?id=24a83fec04f4dd142cd92651490ea9c0-105ac1d5bf768d76df90c5569141bd7f" rel="nofollow">here</a>. Also, as you can see, this method can be "configured" to use std::shared_ptr, raw pointers, ... and with different ownership semanthics, notice the line:</p> <pre><code>std::unique_ptr&lt;Parent&gt; b(mrp["Child2"]("two")); </code></pre> <p>However, any variation of what you briefly described in the question is, well, a variation of it! What you are trying to do is an abstract factory, which "standard" implementation relies exactly on making a factory function for each class you want to build. As I said, it doesn't need to be a static member of the class, it can well be a non-member non-friend function but this doesn't change very much (except better encapsulation, and the need for the constructor being public, or for the factory to be friend, which, somehow, breaks encapsulation).</p> <p>The object factory is implemented in a very elegant way in <a href="http://loki-lib.cvs.sourceforge.net/loki-lib/loki/include/loki/Factory.h?view=markup" rel="nofollow">loki</a>. Refer to Modern C++ (Alexandrescu) for a thorough discussion of the design pattern itself as well as of the implementation given by loki.</p> <p>As for your edit: registration in loki is sweet and simple as in (cited from the book):</p> <pre><code>// Implementation module for class Line // Create an anonymous namespace // to make the function invisible from other modules namespace { Shape* CreateLine() { return new Line; } // The ID of class Line const int LINE = 1; // Assume TheShapeFactory is a singleton factory // (see Chapter 6) const bool registered = TheShapeFactory::Instance().RegisterShape( LINE, CreateLine); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload