Constructing a class from a line in a parameter file
The approach to doing this is two-fold. Firstly, you'll want to modify your classes to have a constructor taking an std::istringstream&amp; as an argument. The second part will be to make a map of strings to constructor functions. So let's assume our (skeleton) classes look something like:

class Potential
{
public:

    virtual ~Potential() { }

    virtual void print() const = 0;

};

class NFW
  : public Potential
{
private:

    double rho0;
    double rs;

public:

    NFW(std::istringstream&amp; iss)
    {
        iss &gt;&gt; rho0 &gt;&gt; rs;
    }

    virtual ~NFW() = default;

    virtual void print() const override
    {
        std::cout &lt;&lt; "NFW: rho0: " &lt;&lt; rho0 &lt;&lt; ", rs: " &lt;&lt; rs &lt;&lt; "\n";
    }
};

class MiyamotoNagai
  : public Potential
{
private:

    double m, a, b;

public:

    MiyamotoNagai(std::istringstream&amp; iss)
    {
        iss &gt;&gt; m &gt;&gt; a &gt;&gt; b;
    }

    virtual ~MiyamotoNagai() = default;

    virtual void print() const override
    {
        std::cout &lt;&lt; "MiyamotoNagai m: " &lt;&lt; m &lt;&lt; ", a: " &lt;&lt; a 
                  &lt;&lt; ", b: " &lt;&lt; b &lt;&lt; "\n";
    }
};


We then define the type our map will hold: it will hold a function that will return a std::shared_ptr&lt;Potential&gt;, and will take a std::istringstream&amp; as an argument:

using function_t = std::function&lt;std::shared_ptr&lt;Potential&gt;(std::istringstream&amp;)&gt;;


Using this, our map becomes:

std::unordered_map&lt;std::string, function_t&gt; register_map;


To add to this, we just need some very simple lambda functions that forward to the corresponding constructor:

register_map["NFW"] = [](std::istringstream&amp; iss) { return std::make_shared&lt;NFW&gt;(iss); };
register_map["MiyamotoNagai"] = [](std::istringstream&amp; iss) { return std::make_shared&lt;MiyamotoNagai&gt;(iss); };


The function to actually create our Potential subclass then looks like:

std::shared_ptr&lt;Potential&gt; create_potential(std::istringstream&amp; iss)
{
    std::string potential_type;
    iss &gt;&gt; potential_type;
    auto it = register_map.find(potential_type);
    if(it == register_map.end()) {
        throw ParseError("Unknown Potential " + potential_type);
    }
    return it-&gt;second(iss);
}


With this, each constructor will need to do its own checking and error handling (which I've omitted above). As written, this better adheres to the open-closed principle (code should be open for extension, closed for modification), as the only thing you should have to touch when you create another subclass is adding another call to register_class[...].

A test example:

int main()
{
    register_map["NFW"] = [](std::istringstream&amp; iss) { return std::make_shared&lt;NFW&gt;(iss); };
    register_map["MiyamotoNagai"] = [](std::istringstream&amp; iss) { return std::make_shared&lt;MiyamotoNagai&gt;(iss); };
    std::istringstream iss("NFW 5 4");
    auto test = create_potential(iss);
    test-&gt;print();
}


As a final point, make absolutely sure this needs a shared_ptr over a unique_ptr. Without context it is impossible to tell, but you should always reach for unique_ptr first, and shared_ptr only if it is absolutely necessary; it may be in this case, but it is still something to very carefully think about.