Unique_ptr 在 class

Unique_ptr in a class

人类 class 原来是非复制的,因为它包含一个类型 unique_ptr 的字段,其复制构造函数和复制赋值运算符已被删除。这可以防止编译器自动为 Human class 生成复制构造函数和赋值运算符。 如何在 Human class 中实现复制构造函数和复制赋值运算符?如果原来的人类拥有猫,则人类的副本必须拥有猫的副本。

struct Cat {
    Cat(const string& name, int age)
        : name_(name)
        , age_(age)  //
    {
    }
    const string& GetName() const noexcept {
        return name_;
    }
    int GetAge() const noexcept {
        return age_;
    }
    ~Cat() {
    }
    void Speak() const {
        cout << "Meow!"s << endl;
    }

private:
    string name_;
    int age_;
};

unique_ptr<Cat> CreateCat(const string& name) {
    return make_unique<Cat>(name, 2);
}

class Human {
public:
    explicit Human(const string& name)
        : name_(name) {
    }
    
    const string& GetName() const noexcept {
        return name_;
    }
    void SetCat(unique_ptr<Cat>&& cat) noexcept {
        cat_ = std::move(cat);
    }
    unique_ptr<Cat> ReleaseCat() noexcept {
        return std::move(cat_);
    }

private:
    string name_;
    unique_ptr<Cat> cat_;
}; 

你的复制构造函数可能看起来像

Human::Human(const Human& rhs) :
    name_(rhs.name_),
    cat_(rhs.cat_ ? std::make_unique<Cat>(*rhs.cat_) : std::nullptr)
{}

但去掉 std::unique_ptr 并按值(或 std::optional<Cat>)设置 Cat 会更简单:

Human::Human(const Human&) = default;

如果 Cat 是多态的,则需要 clone 方法:

Human::Human(const Human& rhs) :
    name_(rhs.name_),
    animal_(rhs.animal_ ? rhs.animal_->clone() : std::nullptr)
{}