Инициализация константных полей в конструкторе

Поля const в C++ должны быть инициализированы в списке инициализации, что делает нетривиальным вычисление взаимозависимых значений из параметров конструктора.

Как лучше всего перевести, например, этот фрагмент кода Java на C++?

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

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

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

    reader.close();
  }
}

Я думал об инкапсуляции подобъекта в SomeObject, но это только перекладывает проблему; или построение объекта с использованием статического метода:

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)
    {};
}

Есть ли лучшее решение?

Спасибо.

3 ответа

Решение

Это отличное приложение для делегирования конструктора C++11:

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}} {}
};

Вы можете использовать делегирующий ctor и лямбда-функцию, например так:

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

Тем не менее, гораздо лучшая идея, вероятно, заключается в редизайне, чтобы использовать все то, что вы можете делать в C++, а что нет в Java.

Я думаю, что у вас правильный подход.

Я бы порекомендовал пару небольших изменений.

Это не правильно C++.

  SomeReader reader = new SomeReader(input_filename);

Возможно, вы имели в виду:

  SomeReader reader(input_filename);

Вы можете изменить строки:

  SomeObject obj(str, i);
  return obj;

в

  return SomeObject(str, i);
Другие вопросы по тегам