考虑这段代码。我已经为Person
定义了一个复制构造函数,它将复制除了一个数据之外的所有数据,即它的DontCopy
数据成员。但是我似乎不能用赋值运算符完成同样的事情。除了下面我已经做过的之外,还有什么最好的方法来完成它呢?目前,我只手动设置了name
成员。如果Person
有数百个成员需要复制,只有一个成员不需要复制,该怎么办?复制构造函数会处理这个问题,而赋值运算符不会。
#include <iostream>
#define show(variable) std::cout << #variable << " = " << variable << '\n';
struct DontCopy {
class Person& subject;
DontCopy (Person& p) : subject(p) { }
};
class PersonDataDoCopy {
protected:
std::string name;
PersonDataDoCopy (const std::string& n) : name(n) { }
PersonDataDoCopy() = default;
};
class Person : private PersonDataDoCopy {
DontCopy dontCopy{*this};
public:
Person (const std::string& n) : PersonDataDoCopy(n) { }
Person (const Person& other) : PersonDataDoCopy(other) { } // 'dontCopy' is not copied from 'other'.
Person (Person&& other) : PersonDataDoCopy(std::move(other)) { } // 'dontCopy' is not copied from 'other'.
Person& operator= (const Person& other) {
if (this == &other)
return *this;
// static_cast<PersonDataDoCopy>(*this) = PersonDataDoCopy(other); // Does not copy data from PersonDataDoCopy
// *this = static_cast<Person&>(PersonDataDoCopy(other)); // Does not compile.
name = other.name; // Need more general solution than this.
return *this;
}
Person() = default;
void display() const { show(name) show(this) show(&dontCopy.subject); }
};
int main() {
Person bob("Bob");
bob.display();
std::cout << '\n';
Person clone1(bob);
clone1.display();
std::cout << '\n';
Person clone2("");
clone2 = bob;
clone2.display();
}
输出:
name = Bob
this = 0x6ffde0
&dontCopy.subject = 0x6ffde0
name = Bob
this = 0x6ffdd0
&dontCopy.subject = 0x6ffdd0
name = Bob
this = 0x6ffdc0
&dontCopy.subject = 0x6ffdc0
1条答案
按热度按时间uemypmqf1#
如果不想逐个复制每个数据成员,可以将所有要复制的数据放入另一个结构中,类似于不复制结构。将所有要复制的数据成员放入该结构中,然后只需将该结构复制到新对象上。
然而,对于类来说,这不是一个特别好的设计,我建议如果你有一个既有数百个数据成员又需要复制构造函数的类,你最好重新设计这个类,把它分解一下。
还有一个问题是在复制构造函数中有一个非复制的数据成员。当你复制一个对象时,大多数人会期望你收到一个对象的精确副本,而不是一个缺少一些东西的部分副本。如果有人试图将对象的副本传递给一个函数,而没有注意到复制构造函数在做什么,这可能会导致bug。
如果你的类包含了不应该被复制的数据,最好将复制构造函数标记为已删除,并使类不可复制。如果你真的需要部分复制行为,你可以将其添加为一个方法,其名称更明显地表明它正在做什么。