万无一失的复制重载:如何不处理应该默认复制的成员?

时间:2015-03-24 12:59:11

标签: c++

随着std::unique_ptr等最新C ++类的使用越来越多,我发现很多默认情况下无法复制使用它们的成员。这很好,因为它们不能被复制:如果父类必须是可复制的,那些成员需要明确地处理。

但是我发现重载复制构造函数/运算符不方便。每个成员都需要明确复制,即使是那些不需要特殊处理的成员。而且,当添加成员时,代码维护者必须记住将此成员添加到复制功能中。我发现这个代码维护者未能做到这一点的可能性接近于我的那个。 (我知道至少有一个可以拥有operator = rely on the copy constructor)。

所以我想知道是否有有效的方法来重载复制构造函数/运算符,这样就不需要为默认复制的成员编写代码。

我能想到的一个解决方案是将类分成两部分:放入一个基类成员,默认复制,其余部分放在子类中;仅限子类的重载副本。我觉得这有点不雅,我相信它有缺点。

另一种方法是将不可复制的对象包装到类中,这些类在复制时构造底层的非可复制对象。这可能更好,但只有当这些对象可以独立于其他父类成员进行初始化时才有用。

如果有人有想法或经验可以分享他们如何解决这个问题,我很乐意听到。

1 个答案:

答案 0 :(得分:7)

unique_ptr成员包装在另一种具有特殊行为的类型中(即克隆指针,或任何适当的行为)。或使用clone_ptr代替unique_ptr

然后只声明你的类'复制构造函数和复制赋值运算符为默认值。

这是一种通用模式,当您只需要某些成员的非默认行为时非常有用:不要手动实现整个复制构造函数,必须为每个成员指定行为,使用包装器将特殊行为添加到需要特殊行为的成员,然后包含类只依赖于默认值。

事实上,这只是使用像unique_ptr甚至std::string这样的RAII类型作为成员的概括。而不是必须为记住delete指针成员或free每个char*的包含类编写析构函数,而是让每个成员做正确的事,并且包含的​​类变为万无一失。

  

这可能更好,但只有当这些对象可以独立于其他父类成员进行初始化时才有用。

它仍然可能,但是包装器可能需要一个指向父类的指针,因此它可以到达其他成员,这会使事情稍微复杂化。

如果您拥有无法独立初始化的相关成员,则可以将相关成员分组为另一种类型,这些类型对所有成员一起做正确的事情。如果有其他成员可以独立初始化,那么仍然可以更容易将它们组合成父类。

同样,你使每个子对象独立且万无一失,因此它们可以像简单的构建块一样组成。如果有成员不是独立的,他们应该属于同一个构建块。