dvilela
dvilela

Reputation: 1262

How to initialize class member outside the member initializer list

I have a C++ class that takes a string (file path) in its constructor, loads that file into a JSON and then uses some of the JSON variables to initialize another member.

As the file needs to be loaded first, and the the JSON initialized (from stream), I cannot initialize thing in the member initializer list. Should I use another wrapper class for the JSON, use new...? How can I achieve this?

class Dummy
{
    std::string _configFilePath;
    json configJson;
    Thing thing;

    Dummy(std::string configFilePath = "../config.json") :
    _configFilePath(configFilePath)
    {
        std::ifstream ifs(configFilePath);
        ifs >> configJson;
        thing(configJson["whatever"]); // thing can't be initialized here
    }
};

Note that thing is not default constructible.

Upvotes: 1

Views: 612

Answers (3)

R Sahu
R Sahu

Reputation: 206747

You can use the combination of a delegating constructor and a helper function that loads the json object to properly initilize the objects.

class Dummy
{
    std::string _configFilePath;
    json _configJson;
    Thing _thing;

    // Use a delegating constructor
    Dummy(std::string configFilePath = "../config.json") :
       Dummy(configFilePath, getConfig(configFilePath) {}

    Dummy(std::string configFilePath, json configJson) :
       _configFilePath(configFilePath),
       _configJson(configJson),
       _thing(configJson["whatever"]) {}

    // Load and return the json object.
    static json getConfig(std::string configFilePath)
    {
       std::ifstream ifs(configFilePath);
       json configJson;
       ifs >> configJson;
       return configJson;
    }
};

Upvotes: 2

1201ProgramAlarm
1201ProgramAlarm

Reputation: 32727

You can use a helper function to do what the current constructor does:

class Dummy
{
    std::string _configFilePath;
    json configJson;
    Thing thing;

    Thing loader() {
        std::ifstream ifs(_configFilePath);
        ifs >> configJson;
        return Thing(configJson["whatever"]);
    }

    Dummy(std::string configFilePath = "../config.json") :
        _configFilePath(configFilePath), thing(loader())
    {
    }
};

This will construct _configFilePath and default construct configJson, then call loader to load the thing. RVO should enable construction of thing directly in loader.

Upvotes: 2

Cory Kramer
Cory Kramer

Reputation: 118031

Is Thing both default constructable and move-assignable? If so:

class Dummy
{
    std::string _configFilePath;
    json configJson;
    Thing thing;

    Dummy(std::string configFilePath = "../config.json") :
    _configFilePath(configFilePath)
    {
        std::ifstream ifs(configFilePath);
        ifs >> configJson;
        thing = Thing(configJson["whatever"]);   // move-assign a new object
    }
};

Upvotes: 2

Related Questions