- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我试图理解作者在他的新书(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/
我正在使用 Gunicorn 为 Django 应用程序提供服务,它工作正常,直到我将其超时时间从 30 秒更改为 900000 秒,我不得不这样做,因为我有一个用例需要上传和处理一个巨大的文件(过程
我有一个带有非常基本的管道的Jenkinsfile,它可以旋转docker容器: pipeline { agent { dockerfile { args '-u root' } } stag
在学习 MEAN 堆栈的过程中,我遇到了一个问题。每当我尝试使用 Passport 验证方法时,它都不会返回任何响应。我总是收到“localhost没有发送任何数据。ERR_EMPTY_RESPONS
在当今的大多数企业堆栈中,数据库是我们存储所有秘密的地方。它是安全屋,是待命室,也是用于存储可能非常私密或极具价值的物品的集散地。对于依赖它的数据库管理员、程序员和DevOps团队来说,保护它免受所
是否可以创建像图片上那样的边框?只需使用 css 边框属性。最终结果将是没 Angular 盒子。我不想添加额外的 html 元素。我只想为每个 li 元素添加 css 边框信息。 假设这是一个 ul
我是一名优秀的程序员,十分优秀!