【问题标题】:initializing const fields in the constructor在构造函数中初始化 const 字段
【发布时间】:2014-09-10 17:51:14
【问题描述】:

C++ 中的 const 字段必须在初始化列表中初始化,这使得从构造函数参数计算相互依赖的值变得非常重要。

将例如这段 java 代码翻译成 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();
  }
}

我想过在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)
    {};
}

有没有更好的解决方案?

谢谢。

【问题讨论】:

  • 这个问题可能更适合codereview.stackexchange.com
  • 恕我直言,要避免在构造函数中访问复杂的资源,例如文件。我很想创建一个工厂类来从 SomeReader 构造您的 SomeObject。使您的 SomeObject 构造函数将最终(const)成员的值作为参数。编辑:您的第二个解决方案是我的建议 - 抱歉我错过了:o)
  • @Jubobs:不,实际上不会。
  • @Deduplicator 我不知道。 有更好的解决方案吗?什么是最好的方法 [...]? 向我尖叫“代码审查”。你能详细说明一下吗?
  • IMO 在这种情况下拥有const 数据成员很少值得麻烦。它还可以防止自动生成复制/移动赋值运算符。

标签: c++ constructor constants ctor-initializer


【解决方案1】:

这是一个很棒的 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}} {}
};

【讨论】:

    【解决方案2】:

    我认为你的方法是正确的。

    我会推荐几个小的改动。

    这不是正确的 C++。

      SomeReader reader = new SomeReader(input_filename);
    

    也许你的意思是:

      SomeReader reader(input_filename);
    

    你可以换行:

      SomeObject obj(str, i);
      return obj;
    

      return SomeObject(str, i);
    

    【讨论】:

    • 你说得对,我翻译的时候忘记改了。 TY
    【解决方案3】:

    您可以使用 委托 ctorlambda-function,如下所示:

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

    不过,一个更好的想法可能是重新设计,以利用您在 C++ 中可以做而在 Java 中不能做的所有事情。

    【讨论】:

      猜你喜欢
      • 2010-11-28
      • 2011-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-11
      • 1970-01-01
      • 2018-04-23
      相关资源
      最近更新 更多