如何在没有复制构造函数的情况下克隆对象
How to clone an object without copy constructor
根据 CppCoreGuideline,我应该禁用基的复制构造函数 class 并提出一个克隆方法:https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-copy-virtual
例如:
class B {
public:
explicit B() = default;
B(B&&) = default; // Move constructor
B& operator=(B&&) = default; // Move assignment operator
B(const B&) = delete; // Copy constructor
B& operator=(const B&) = delete; // Copy assignment
virtual ~B() = default;
virtual unique_ptr<B> clone()
{
return unique_ptr<B>{new B{*this}}; // how do this without copy constructor ?
}
private:
int c;
int d;
};
class D : public B {
public:
explicit D() = default;
D(D&&) = default; // Move constructor
D& operator=(D&&) = default; // Move assignment operator
D(const B&) = delete; // Copy constructor
D& operator=(const D&) = delete; // Copy assignment
virtual ~D() = default;
virtual unique_ptr<B> clone() override
{
// how can I copy all private data member of base class ???
}
};
但是如何在克隆方法中复制所有私有数据成员?显然,我将使用 CRTP 模式:C++: Deep copying a Base class pointer
与其禁用复制构造函数,不如考虑将其标记为受保护。这样,class 的客户端就不会意外地创建副本,但是 class 的实例可以根据需要调用复制构造函数来实现 clone
函数。假设您没有进行任何显式资源管理,则可以使用复制构造函数的默认版本。然后,要实现 clone
,您可以这样做:
virtual unique_ptr<B> clone() override
{
return make_unique<D>(*this);
}
这会调用对象自己的(受保护的)复制构造函数,后者又会调用基类的(受保护的)复制构造函数等。
请注意,这里不需要使用 CRTP。使用好的老式复制构造函数应该就是您所需要的。
我认为最简单的方法是实际制作特殊成员 protected
而不是 deleted
。这仍然可以防止切片,但可以更容易地实现 clone()
。请注意,复制和移动成员都需要这样处理。
class B {
public:
// if this is truly intended to be a polymorphic base class, it probably
// doesn't make sense for the base to be able to clone itself.
virtual unique_ptr<B> clone() = 0;
protected:
B(B const& ) = default;
B& operator=(B const& ) = default;
private:
int c;
int d;
};
这也允许派生的 类 轻松做到这一点:
class D : public B {
public:
D(D const& ) = default; // this is safe now
D& operator=(D const& ) = default;
unique_ptr<B> clone() override {
return unique_ptr<D>(new D(*this));
}
// ...
};
根据 CppCoreGuideline,我应该禁用基的复制构造函数 class 并提出一个克隆方法:https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-copy-virtual
例如:
class B {
public:
explicit B() = default;
B(B&&) = default; // Move constructor
B& operator=(B&&) = default; // Move assignment operator
B(const B&) = delete; // Copy constructor
B& operator=(const B&) = delete; // Copy assignment
virtual ~B() = default;
virtual unique_ptr<B> clone()
{
return unique_ptr<B>{new B{*this}}; // how do this without copy constructor ?
}
private:
int c;
int d;
};
class D : public B {
public:
explicit D() = default;
D(D&&) = default; // Move constructor
D& operator=(D&&) = default; // Move assignment operator
D(const B&) = delete; // Copy constructor
D& operator=(const D&) = delete; // Copy assignment
virtual ~D() = default;
virtual unique_ptr<B> clone() override
{
// how can I copy all private data member of base class ???
}
};
但是如何在克隆方法中复制所有私有数据成员?显然,我将使用 CRTP 模式:C++: Deep copying a Base class pointer
与其禁用复制构造函数,不如考虑将其标记为受保护。这样,class 的客户端就不会意外地创建副本,但是 class 的实例可以根据需要调用复制构造函数来实现 clone
函数。假设您没有进行任何显式资源管理,则可以使用复制构造函数的默认版本。然后,要实现 clone
,您可以这样做:
virtual unique_ptr<B> clone() override
{
return make_unique<D>(*this);
}
这会调用对象自己的(受保护的)复制构造函数,后者又会调用基类的(受保护的)复制构造函数等。
请注意,这里不需要使用 CRTP。使用好的老式复制构造函数应该就是您所需要的。
我认为最简单的方法是实际制作特殊成员 protected
而不是 deleted
。这仍然可以防止切片,但可以更容易地实现 clone()
。请注意,复制和移动成员都需要这样处理。
class B {
public:
// if this is truly intended to be a polymorphic base class, it probably
// doesn't make sense for the base to be able to clone itself.
virtual unique_ptr<B> clone() = 0;
protected:
B(B const& ) = default;
B& operator=(B const& ) = default;
private:
int c;
int d;
};
这也允许派生的 类 轻松做到这一点:
class D : public B {
public:
D(D const& ) = default; // this is safe now
D& operator=(D const& ) = default;
unique_ptr<B> clone() override {
return unique_ptr<D>(new D(*this));
}
// ...
};