在 C++ 中复制具有多态成员的对象
Copying an object with a polymorphic member in C++
我想表达的是,每个类型 V 的对象都拥有一个类型 B 的对象。B 是一个多态类型,因此通过指针或引用访问以防止切片 (C.145)。我觉得很自然地表达如下
class B {};
class V {
public:
unique_ptr<B> p;
};
我现在可以推导 B 并将推导的结果分配给 p,这样
class D : public B {};
V x;
x.p = make_unique<D>();
因为B是多态类型,建议抑制复制和移动以防止切片(C.67)。
B(const B&) = delete;
// etc...
不可能复制 p,因为它是一个 unique_ptr,我现在也阻止了深度复制,除非实现了克隆功能 (C.130)。虚拟克隆功能的实现是否表明设计不当?这似乎是一种解决方法。
通过遵循 C++ Core Guidelines 中的这两条规则,我阻止了 V 的复制。如果 V 是图中的一个顶点,并且必须复制图,那么我就给自己制造了一个问题;无法再复制任何图形。为 V 实现自定义复制分配并不能解决该问题,因为不可能对 p 进行深度复制。
在网上找了一圈,没有找到感觉自然的解决方案,我断定我的思路一定有很大的问题。拥有多态成员是个坏主意吗?如果不应该复制多态对象,那么就不能复制任何拥有另一个多态对象的对象。
成员可以是 shared_ptr,但语义会出错,因为这不是共享对象。我缺乏一种表达明显易于概念化的东西的方法。如何在不牺牲语义的情况下复制拥有另一个多态对象的对象?每 post 我读到有人提出关于复制 unique_ptr、深度复制等的问题,通常都会得到一个需要牺牲的答案,很可能是因为解决问题的方式问题一开始就错了。我觉得有一个非常简单而优雅的解决方案。
你需要问自己一个问题:为什么 B 不能被复制?
你描述的例子,一个图拥有一个(或可能多个)顶点显示相反:B 应该是可复制的!
你不想要的是两个图共享同一个顶点实例。
因此您可以按照这些行为 V 创建复制构造函数/克隆方法:
V::V(const V& other)
{
p = other.p->clone();
}
std::unique_ptr<B> D::clone()
{
return std::make_unique<D>(...);
}
查看 this article 以获得更好的解释。
我想表达的是,每个类型 V 的对象都拥有一个类型 B 的对象。B 是一个多态类型,因此通过指针或引用访问以防止切片 (C.145)。我觉得很自然地表达如下
class B {};
class V {
public:
unique_ptr<B> p;
};
我现在可以推导 B 并将推导的结果分配给 p,这样
class D : public B {};
V x;
x.p = make_unique<D>();
因为B是多态类型,建议抑制复制和移动以防止切片(C.67)。
B(const B&) = delete;
// etc...
不可能复制 p,因为它是一个 unique_ptr,我现在也阻止了深度复制,除非实现了克隆功能 (C.130)。虚拟克隆功能的实现是否表明设计不当?这似乎是一种解决方法。
通过遵循 C++ Core Guidelines 中的这两条规则,我阻止了 V 的复制。如果 V 是图中的一个顶点,并且必须复制图,那么我就给自己制造了一个问题;无法再复制任何图形。为 V 实现自定义复制分配并不能解决该问题,因为不可能对 p 进行深度复制。
在网上找了一圈,没有找到感觉自然的解决方案,我断定我的思路一定有很大的问题。拥有多态成员是个坏主意吗?如果不应该复制多态对象,那么就不能复制任何拥有另一个多态对象的对象。
成员可以是 shared_ptr,但语义会出错,因为这不是共享对象。我缺乏一种表达明显易于概念化的东西的方法。如何在不牺牲语义的情况下复制拥有另一个多态对象的对象?每 post 我读到有人提出关于复制 unique_ptr、深度复制等的问题,通常都会得到一个需要牺牲的答案,很可能是因为解决问题的方式问题一开始就错了。我觉得有一个非常简单而优雅的解决方案。
你需要问自己一个问题:为什么 B 不能被复制?
你描述的例子,一个图拥有一个(或可能多个)顶点显示相反:B 应该是可复制的! 你不想要的是两个图共享同一个顶点实例。
因此您可以按照这些行为 V 创建复制构造函数/克隆方法:
V::V(const V& other)
{
p = other.p->clone();
}
std::unique_ptr<B> D::clone()
{
return std::make_unique<D>(...);
}
查看 this article 以获得更好的解释。