将派生类unique_ptr分配给基类unique_ptr

时间:2016-06-16 05:37:29

标签: c++ oop c++11 unique-ptr

我创建了一个从std :: istream派生的自定义istream,当文件是压缩文件时使用自定义streambuf,否则使用std :: filebuf。

#mystream.h
class my_stream: public istream {
  public:
     explicit my_stream(const std::string &path);
  private:       
     std::unique_ptr<std::streambuf> b_;
}

#mystream.cpp
my_stream::my_stream(const std::string &path) :std::istream(nullptr) {
    if(path.substr(path.length()-6, path.length())==".gzip"){
        b_ = std::make_unique<gzipbuf>(path); //gzipbuf is derived from std::streambuf
    } 
    else {
        std::unique_ptr<std::filebuf> fb;
        fb->open(path.c_str(), std::ios::in);
        b_ = fb;
    }
    this->init(b_.get());
}

我能够在一个地方将派生类unique_ptr分配给基类unique_ptr

b_ = std::make_unique<gzipbuf>(path);

但不在另一个

b_ = fb;

它说 候选函数不可行:没有来自'unique_ptr&gt;&gt;'的已知转换'unique_ptr,default_delete&gt;&gt;'第一个论点       operator =(unique_ptr&amp;&amp; __u)noexcept

1 个答案:

答案 0 :(得分:7)

首先,在此行之后

std::unique_ptr<std::filebuf> fb;

fb实际上并没有指向任何内容,它只是一个空unique_ptr所以你在这里调用未定义的行为:

fb->open(path.c_str(), std::ios::in);

要解决此问题,只需将行更改为:

auto fb = std::make_unique<std::filebuf>();

关于您获得的错误,如果允许此行

b_ = fb;
然后

然后b_fb都会指向同一个对象。 unique_ptr不允许这样做。资源可以由一个unique_ptr拥有,只有一个。fb。一种解决方案是使用b_将所有权从std::move传递到b_ = std::move(fb)

fb

然后streambuf不再拥有任何东西。

就个人而言,我喜欢尽可能在构造函数初始化列表中初始化成员变量,并将std::unique_ptr<std::streambuf> createStream(const std::string &path) { if(path.substr(path.length()-5, path.length())==".gzip"){ // I think you meant 5 here! return std::make_unique<gzipbuf>(path); } auto fb = std::make_unique<std::filebuf>(); fb->open(path.c_str(), std::ios::in); return fb; } 的创建提取到单独的函数中,以便这样做:

my_stream

然后my_stream::my_stream(const std::string &path) : std::istream(nullptr), b_(createStream(path)) { this->init(b_.get()); } 的构造函数可以是:

{{1}}