给定多个派生类的基类,目标是创建一个包装类,允许STL容器查看具有基本接口事件的对象,尽管不同的派生类可能实际上是添加到容器中。 (见Retrieve data from heterogeneous std::list)。unique_ptr成员,私人拷贝构造函数与移动构造函数
经过一番修补之后,我想出了一个新的派生类,它是一个基类unique_ptr
的包装。然而,移动构造函数让我感到困惑。
class Base {
friend class BaseWrapper;
virtual Base * clone() const = 0;
public:
virtual ~Base() {}
//... public interface
};
class Derived : public Base {
//... specific members for derived class
Base * clone() const { return new Derived(*this); }
public:
//... implement public interface
};
class BaseWrapper : public Base {
std::unique_ptr<Base> ptr_;
Base * clone() const { return ptr_->clone(); }
public:
BaseWrapper (const Base &b) : ptr_(b.clone()) {}
//... implement public interface by forwarding to ptr_
};
typedef std::list<BaseWrapper> BaseList;
int main() {
BaseList l;
l.push_back(Derived());
}
This does not compile with g++ 4.7.2。
现在,为了使用BaseWrapper
,我可以实现公众移动构造函数是这样的:
BaseWrapper (BaseWrapper &&bw) { ptr_.swap(bw.ptr_); }
And this works fine。但是,如果我将其设为私人,it will not compile。
然而,我发现不是上述情况,I can instead define a private "copy" constructor(使其成为公众也适用,当然):
BaseWrapper (BaseWrapper &bw) { ptr_.swap(bw.ptr_); }
有人能告诉我,如果这是这样运作的,以及为什么或者为什么不呢?如果它应该工作,为什么我不能使移动构造函数为私有?
你可以按照this link来更完整地说明上述玩具程序。
我不确定为什么在你的例子中编译器试图使用隐式删除的拷贝ctor,当它应该使用移动ctor。 [例如gcc 4.8](http://liveworkspace.org/code/2cW7iN0.0)编译,但是[clang 3.2它没有](http://liveworkspace.org/code/2fUtBE$0)。 – 2013-04-04 21:49:13
@JesseGood:谢谢。我发现正确使用'unique_ptr'的技巧超过了它的用处,因此我可能会推荐''shared_ptr' over'unique_ptr'。 – jxh 2013-04-04 22:16:57
请注意,删除'virtual〜Base(){}'允许[在g ++ 4.7.2上编译](http://ideone.com/Un5EbY),它可以防止隐式声明移动ctor,并且有一个注释'当移动构造函数未被隐式声明或显式提供时,否则将调用移动构造函数的表达式可能会调用复制构造函数。我仍然不确定谁是对的。 – 2013-04-05 00:25:50