1

我正在使用带有(仅)构造函数的第三方类,如下所示

class foo  // cannot be altered
{
  public:
    explicit foo(std::istream&);
  ...
};

并且其中的文档建议采用以下方法

std::ifstream from("file.txt");
foo obj(from);
from.close();

我无法更改foo并想用作另一个班级的成员

class bar
{
     foo obj;                           // must not be altered
   public:
     explicit
     bar(std::string const&filename)    // must not be altered
       : obj(std::ifstream(filename))   // error: no matching constructor
   {}
   ...
};

除了这不起作用,因为不能保证std::ifstream从 the 创建的临时对象的filename寿命足够长以构造 the foo obj,因此不能转换为 a (如果接受 a std::istream&,情况会有所不同)。foo::foo()const std::istream&

所以我的问题是:我可以在bar不改变设计的情况下使构造函数工作bar(例如,bar::bar()采用 astd::istream&或 bar 来保存 astd::unique_ptr<foo>而不是 afoo或通过向 中添加数据成员bar)?

4

2 回答 2

2

您的设计约束是不可能满足的。最安全的放松方法是坚持std::ifstreambar

class bar
{
     std::ifstream objs_stream;         // must be declared before obj
     foo obj;                           // must not be altered
   public:
     explicit
     bar(std::string const&filename)    // must not be altered
       : objs_stream(filename), obj(objs_stream)
   {}
   ...
};

另一种选择是向第三方类提交补丁:

class foo
{
  public:
    explicit foo(std::istream&);
    explicit foo(std::istream&& is) : foo(is) {}
  ...
};

如果foo有一个复制或移动构造函数,你可以

foo make_foo(const std::string& filename)
{
    std::ifstream is(filename);
    return foo(is);
}

class bar
{
     foo obj;                           // must not be altered
   public:
     explicit
     bar(std::string const&filename)    // must not be altered
       : obj(make_foo(filename))
   {}
   ...
};
于 2020-08-20T13:16:50.207 回答
0

我想出了以下可能性(编译时没有错误)。

class bar
{
    foo obj;                           // must not be altered
    struct tmp {
       mutable std::ifstream s;
       tmp(std::string const&f) : s(f) {}
       operator std::istream&() const { return s; }
    };
  public:
    explicit
    bar(std::string const&filename)    // must not be altered
      : obj(tmp(filename))
  {}
  ...
};

这个可以吗?即将tmp::s一直存在到回报的构建obj(根据文档foo,请参阅已编辑的问题,就足够了)?

于 2020-08-20T13:22:13.107 回答