- 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/
我正在使用 Buildout和 Mr.Developer为了设置我的环境(用于开发和部署)。此设置的一部分是 pull 此项目所需的私有(private) git 存储库。 (这就是我使用 Mr.De
该文档尚不清楚。所有有关Hive LLAP(万岁和流程)的博客文章示例都使用Tez执行引擎,但是Spark / MR Hive引擎也可以使用LLAP吗? 最佳答案 Hive2已弃用MR执行,但仍然可行
从问题中可以得出,我想知道什么时候使用压缩格式(如 gzip)的输入文件是有意义的,什么时候使用未压缩格式的输入文件是有意义的。 压缩文件的开销是多少?读取文件时会慢很多吗?是否对大输入文件进行了基准
ti= /\bMrs\b|\b Mr\b|\bMiss\b|\bMaster\b/; if(!ti.test(title.value)){ alert("Error: Plea
我是一名优秀的程序员,十分优秀!