C++ 将派生类唯一\u ptr分配给基类唯一\u ptr
我创建了一个从std::istream派生的自定义istream,当文件是压缩文件时使用自定义streambuf,否则使用std::filebufC++ 将派生类唯一\u ptr分配给基类唯一\u ptr,c++,oop,c++11,unique-ptr,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.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());
}
上面说
candidate function not viable: no known conversion from 'unique_ptr<std::filebuf, default_delete<std::basic_filebuf<char>>>' to 'unique_ptr<std::basic_streambuf<char>, default_delete<std::basic_streambuf<char>>>' for 1st argument
operator=(unique_ptr&& __u) noexcept
候选函数不可行:第一个参数没有从'unique_ptr'到'unique_ptr'的已知转换
运算符=(唯一\u ptr&&\u_)无例外
首先,在这行之后
std::unique_ptr<std::filebuf> fb;
要解决此问题,只需将行更改为:
auto fb = std::make_unique<std::filebuf>();
然后,b
和fb
都会指向同一个对象。unique\u ptr
不允许这样做。一个资源只能由一个unique\u ptr
拥有。一种解决方案是使用std::move
将所有权从fb
传递到b
:
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;
}
您需要移动它:
b=std::move(fb)代码>因为这里只能有一个(没有副本)。谢谢!这是有道理的。
auto fb = std::make_unique<std::filebuf>();
b_ = fb;
b_ = std::move(fb)
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(const std::string &path) : std::istream(nullptr),
b_(createStream(path)) {
this->init(b_.get());
}