gpt4 book ai didi

c++ - 没看懂Stroustup先生建议删除抽象类Shape的copy default和move操作

转载 作者:可可西里 更新时间:2023-11-01 16:39:33 25 4
gpt4 key购买 nike

我试图理解作者在他的新书(TCPL 第 4 版)中 3.3.4 Suppressing Operations 中的建议,但无济于事。

书摘

Using the default copy or move for a class in a hierarchy is typically a disaster: Given only a pointer to a base, we simply don’t know what members the derived class has (§3.3.3), so we can’t know how to copy them. So, the best thing to do is usually to delete the default copy and move operations; that is, to eliminate to default definitions of those two operations:

class Shape {
public:
Shape(const Shape&) =delete; // no copy operations
Shape& operator=(const Shape&) =delete;
Shape(Shape&&) =delete; //no move operations
Shape& operator=(Shape&&) =delete;
~Shape();
};

Now an attempt to copy a Shape will be caught by the compiler. If you need to copy an object in a class hierarchy, write some kind of clone function (§22.2.4).

例如,下面的代码无法通过 Shape(const Shape&) = delete; 进行编译,因为 clone() 函数会调用 Shape 的复制构造函数。

#include <iostream>

class Shape
{
public:
virtual ~Shape() {}
Shape() {}
Shape(const Shape&) {};
virtual Shape* clone() const = 0;
};

class Circle: public Shape
{
public:
Circle(int i) : a(i) {}
Circle* clone() const { return new Circle(*this); }
int a;
};

int main()
{
Shape* p = new Circle(1);
Shape* q = p->clone();

std::cout << dynamic_cast<Circle*>(p)->a << std::endl;
std::cout << dynamic_cast<Circle*>(q)->a << std::endl;

}

最佳答案

如果您只有一个指向 Shape 的指针,那么您不可能制作实际实现的拷贝 - 它(很可能)会更大,因此您的拷贝将被“切片” ”。在您的示例中,Circle 将有一个额外的 int a;这不是 Shape 类的一部分 - 如果您只是简单地复制一个 Shape 类对象而不知道它是一个 Circle (多态性的全部意义在于,在泛型函数中处理对象时,您不应该“知道”什么对象是什么类型)

为了避免因不小心使用类似的东西而引起的问题:

*q = *p; 

最好“删除”允许您这样做的运算符

但是,由于您描述的情况需要复制构造函数,因此一种解决方案是使其 protected - 防止派生类以外的其他东西使用它,并且可以正常工作。

感谢下面的 robson(还有一个晚上的 sleep ),解决方案显然是在 Circle 中创建一个复制构造函数。仅仅因为您没有 Shape 并不意味着您不能在派生类中拥有一个:

class Circle: public Shape
{
public:
Circle(int i) : a(i) {}
Circle(const Circle& other) { a = other.a; } // Note this line!
Circle* clone() const { return new Circle(*this); }
int a;
};

它尝试使用 Shape 复制构造函数的原因是因为您自己的类中没有。你应该!

您也可以这样做(正如 Robson 解释的那样):

class Circle: public Shape
{
public:
Circle(int i) : a(i) {}
Circle* clone() const { return new Circle(a); }
int a;
};

而且根本不需要复制构造函数。这两种解决方案都解决了“您正在尝试使用已删除的 Shape(const Shape &) 构造函数。一旦您看到它,它真的很明显。

关于c++ - 没看懂Stroustup先生建议删除抽象类Shape的copy default和move操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17912889/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com