Return correct subclass instance, identified by string I have made a function which takes a string which can be any of &quot;triangle&quot;, &quot;square&quot; or &quot;rectangle&quot;.
Depending on the string I return a pointer to an instance of class Form. My class Form has subclasses Triangle, Square and Rectangle.
My constraints were:

use C++98
no STL library (no map, vector etc)
no friend, and no using namespace std;


#include &lt;iostream&gt;
#define NB_FORMS 3

/**/

class Form
{
  public:
    Form() { }
    virtual ~Form() { }
};

class Square : public Form
{
  public:
    Square() { std::cout &lt;&lt; &quot;Squareee!&quot; &lt;&lt; std::endl; }
     static Form *createForm(void)
     {
       return (new Square());
     }
};

class Rectangle : public Form
{
  public:
    Rectangle() { std::cout &lt;&lt; &quot;Rectangleee!&quot; &lt;&lt; std::endl; }
    static Form *createForm(void)
    {
      return (new Rectangle());
    }
};

class Triangle : public Form
{
  public:
    Triangle() { std::cout &lt;&lt; &quot;Triangleee!&quot; &lt;&lt; std::endl; }
    static Form *createForm(void)
    {
      return (new Triangle());
    }
};

struct        s_makeForms
{
    std::string        formName;
    Form            *(*makeForm)();
};

/* */

Form *func(std::string name)
{
  struct s_makeForms allForms[3] =
  {
      {&quot;triangle&quot;,  Triangle::createForm}, 
      {&quot;rectangle&quot;, Rectangle::createForm},
      {&quot;square&quot;, Square::createForm}
  };
  for (int i = 0; i &lt; NB_FORMS; i++)
  {
    if (name == allForms[i].formName)
      return (allForms[i].makeForm());
  }
  return (NULL);
}

int main()
{
  Form *myform;

  if (!(myform = func(&quot;square&quot;)))
  {
    std::cerr &lt;&lt; &quot;wrong name&quot; &lt;&lt; std::endl;
  }
  delete myForm;
}
Use all the power of the standard library
In your post on StackOverflow, you mentioned that you couldn't use std::map because you were not allowed to use it. Outside of the classroom, you should not limit yourself this way, and instead use the appropriate functions from the standard library that help you write concise and efficient code. The function func() could look like:
Form *func(std::string_view name)
{
    static const std::unordered_map&lt;std::string_view, std::function&lt;Form*()&gt;&gt; forms = {
        {&quot;triangle&quot;,  []{return new Triangle;}},
        {&quot;rectangle&quot;, []{return new Rectangle;}},
        ...
    };

    if (auto found = forms.find(name); found != forms.end()) {
        return found-&gt;second();
    } else {
        return nullptr;
    }
}

And instead of raw pointers, you should probably return std::unique_ptr&lt;Form&gt;.
In the rest of the review I'm going to assume you are limited to what you can use.
Prefer using = default
It's usually best to let the compiler generate default constructors, destructors and other operators. In some cases, you have to explicitly tell it to add one of those, for example when you want to ensure the destructor of Form is virtual. In that case, use = default instead of {}:
class Form
{
public:
    virtual ~Form() = default;
};

Use \n instead of std::endl
Prefer using \n instead of std::endl, the latter is equivalent to the former but also forces a flush of the output, which might be bad for performance if you are printing a lot.
Avoid unnnecessary parentheses and void
You can simplify the createForm() functions a bit:
static Form *createForm()
{
    return new Square;
}

The unnecessary parentheses and void in the argument list are just unnecessary distractions here.
Move s_makeForms into func()
You can move the definition of struct s_makeForm into func(), so it doesn't clutter the global namespace. In fact, you don't even have to give this struct a name, you can write:
Form *func(std::string &amp;name)
{
    struct {
        std::string name;
        Form *(*createForm)();
    } forms[] = {
        &quot;triangle&quot;, Triangle::createForm},
        ...
    }

    ...
}

Prefer const std::string &amp; when passing string arguments
To avoid unnecessary copying of strings, prefer passing strings as const references:
Form *func(const std::string &amp;name)
{
    ...
}

Avoid having to #define NB_FORMS
You can get the size of the array allForms in various ways, the typical trick that works both in C and all versions of C++ is:
struct ... allForms[] = {...};
size_t numForms = sizeof allForms / sizeof *allForms;

for (size_t i = 0; i &lt; numForms; ++i)
{
    ...
}

You can also use a range-based for-loop to iterate over the array:
struct ... allForms[] = {...};

for (auto &amp;form: allForms)
{
    if (name == form.formName)
        return form.makeForm();
}

Memory leak
There is a memory leak in your program, since you forgot to call delete myform. These kinds of errors can be avoided by using smart pointers, such as std::unique_ptr.