- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
当我需要多态行为时,我经常发现自己在 C++ 中使用唯一指针。我通常实现如下所示的纯抽象类:
class A {
public:
virtual A* clone() const = 0; // returns a pointer to a deep copy of A
// other methods go here
};
当我想用它自己的 A 实例来修饰另一个类时,clone 方法就派上用场了,例如:
#include <memory>
class B {
private:
std::unique_ptr<A> a_ptr;
public:
// ctor
B(const A& a) {
a_ptr = std::unique_ptr<A>(a.clone());
//...
}
// copy ctor
B(const B& other) : B(*other.a_ptr) {}
};
我总是最终在 B 中实现复制构造函数以避免编译器错误(MSVC 给出了关于尝试引用已删除函数的模糊消息),因为唯一指针,这是完全有意义的。我的问题可以总结如下:
我真的需要 B 中的复制构造函数吗?也许有一个更好的模式可以让我完全避免它。
如果 1 是,我可以就此打住吗?我是否需要实现其他默认功能? IE。有没有我还需要默认构造函数和析构函数的场景?
在实践中,每当我觉得需要实现默认函数时,我通常会在其他三个函数的旁边实现一个移动构造函数;我通常使用 copy-and-swap 惯用语(根据 GManNickG's answer in this thread )。我认为这不会改变任何东西,但也许我错了!
非常感谢!
最佳答案
首先,我认为您的克隆函数的签名可能是
virtual std::unique_ptr<A> clone() = 0;
因为您想要 A
实例的深层拷贝和 B
中的独占所有权。其次,当您希望类可复制时,您确实必须为您的类定义一个复制构造函数。赋值运算符也是如此。这是因为 std::unique_ptr
是一个只能移动的类型,它阻碍了编译器生成默认实现。
不需要其他特殊的成员函数,尽管它们可能有意义。编译器不会为您生成移动构造函数和移动赋值运算符(因为您提供了自己的复制/赋值函数),但在您的情况下,您可以轻松 = default;
它们。析构函数同样可以用 = default;
定义,这符合 core guidelines .
请注意,通过 = default
定义析构函数应该在翻译单元中完成,因为 std::unique_ptr
需要在释放其资源时知道完整类型。
你是否需要默认构造函数完全取决于你想如何使用 B
类。
关于c++ - 唯一指针和 3 法则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51322684/
在 SO解释了为什么像 scalaz、cats (Scala) 或 Arrow (Kotlin) 中的 Validation 不能是 monad。 据我所知,这是因为他们已经根据应用仿函数对 mona
给定例如像 这样的类型 data Tree a = Branch (Tree a) (Tree a) | Leaf a 我可以轻松地为 Functor、Applicative、
从这里引用:https://en.wikipedia.org/wiki/Law_of_Demeter More formally, the Law of Demeter for functions r
以下代码打破了 Law of Demeter : public class Student extends Person { private Grades grades; public Stu
我有一个简单的 Store 类,其中包含一个 Inventory。 Inventory 包含一个 Item 列表。为了修改 Inventory 中的其中一个 Item,我必须这样写: Store st
public class BigPerformance { public decimal Value { get; set; } } public class Performance
当我需要多态行为时,我经常发现自己在 C++ 中使用唯一指针。我通常实现如下所示的纯抽象类: class A { public: virtual A* clone() const = 0; /
5 规则指出,如果一个类有一个用户声明的析构函数、复制构造函数、复制赋值构造函数、移动构造函数或移动赋值构造函数,那么它必须有其他 4 个。 但今天我突然明白了:你什么时候需要用户定义的析构函数、复制
编译器或库的更“ native ”部分(IO 或可以访问黑魔法和实现的函数)是否对这些定律做出假设?打破它们会导致不可能的事情发生吗? 或者它们只是表达了一种编程模式——也就是说,你唯一会因为破坏它们
我有点想用 Java 8 流编写 Selenium 页面对象,如下面的代码所述,并收到评论说我的代码违反了 Demeter 法则,因为我在一行中执行了很多操作。我被建议将代码分解为第一个流以收集列表并
我对如何避免一对多关联违反得墨忒耳法则感到困惑。假设我有一个这样的模型: class Organization < ActiveRecord::Base has_one :address ha
如果我有一个对象的 ArrayList,那么任何时候我需要调用 ArrayList 成员的任何方法时,我都需要这样做: list.get(i).doSomething(); 这看起来很可疑地违反了 D
我在我的 Purescript 代码中广泛使用了来自库和我自己的类型类。每个类型类法则似乎都提供了一个很好的测试。目前,我正在为每个类(class)和法律单独编写测试。有没有办法部分自动化?也许像 H
我看到提到过 ListT is a classic example of a buggy monad transformer that doesn't satisfy the monad laws.
当我审查一些代码时,我看到了这个片段。 List users = /* Some code that initializes the list */; users.stream() .fil
我是一名优秀的程序员,十分优秀!