factoriel
factoriel

Reputation: 79

initializing const fields in the constructor

const fields in C++ must be initialized in the initialization list, this makes non trivial the computation of interdependent values from the constructor parameters.

What is(are) the best way(s) to translate, for example, this piece of java code into c++ ?

public class SomeObject {
  private final String some_string;
  private final int some_int;

  public SomeObject(final String input_filename){
    SomeReader reader(input_filename);

    some_string = reader.getString();
    some_int = reader.getInt();

    reader.close();
  }
}

I thought of encapsulating a sub-object in SomeObject, but this is just shifting the problem; or constructing the object using a static method:

class SomeObject {
  private:
    const std::string some_string;
    const int some_int;

  public:
    static SomeObject unserialize(const char * input_filename){
      SomeReader reader = new SomeReader(input_filename);

      string str = reader.get_string();
      int i = reader.get_int();

      reader.close();

      SomeObject obj(str, i);
      return obj;
    };

    SomeObject(const std::string str, const int i) :
      some_string(str),
      some_int(i)
    {};
}

Is there a better solution ?

Thank you.

Upvotes: 4

Views: 610

Answers (3)

Casey
Casey

Reputation: 42554

This is a great application for C++11 constructor delegation:

class SomeObject {
  private:
    const std::string some_string;
    const int some_int;

  public:
    // The "real" constructor for SomeObject
    SomeObject(std::string str, const int i) :
      some_string{std::move(str)},
      some_int{i}
    {}

    // Deserialize from SomeReader (delegates to the primary constructor)
    SomeObject(SomeReader& reader) :
      SomeObject{reader.get_string(), reader.get_int()} {}

    // Deserialize from SomeReader (accepts rvalues,
    //   delegates to the lvalue constructor)
    SomeObject(SomeReader&& reader) :
      SomeObject{reader} {}

    // Deserialize from named file (delegates to the SomeReader&& constructor)
    SomeObject(const char* input_filename) :
      SomeObject{SomeReader{input_filename}} {}
};

Upvotes: 5

Deduplicator
Deduplicator

Reputation: 45654

You can use a delegating ctor and a lambda-function, like this:

SomeObject(const char* filename) : SomeObject([&]{
    /* Do calculations here */
    return std::make_tuple(...);
}()) {}
SomeObject(std::tuple<...>&& x) : /* ... */ {}

Still, a much better idea is probably a re-design to make use of all the things you can do in C++ and cannot do in Java.

Upvotes: 1

R Sahu
R Sahu

Reputation: 206577

I think you have the right approach.

I would recommend couple of minor changes.

This is not correct C++.

  SomeReader reader = new SomeReader(input_filename);

Perhaps you meant:

  SomeReader reader(input_filename);

You can change the lines:

  SomeObject obj(str, i);
  return obj;

to

  return SomeObject(str, i);

Upvotes: 1

Related Questions