C++ 中的原型设计模式示例

Prototype Design Pattern Example in C++

提问人:bbbg 提问时间:4/10/2023 更新时间:4/10/2023 访问量:71

问:

我正在学习原型设计模式并实现演示,我将深度复制构造函数和克隆函数添加到这些类中,但我不确定我是否正确实现了它们。我在otherNode中做了dynamic_cast转换,这有点奇怪。有什么建议吗?

class base {
public:
    explicit base() {}
    virtual ~base() = default;
    virtual base* clone() const = 0;
};

class ttNode : public base {
public:
    explicit ttNode() : base() {}
    ~ttNode() = default;
};

class SonNode : public ttNode {
public:
    SonNode() : ttNode() {}
    ~SonNode() = default;

    base* clone() const override {
        return new SonNode(*this);
    }
private:
    int c_{0};
    int a_{0};
};

class FatherNode : public ttNode {
public:
    FatherNode() : ttNode() {}
    ~FatherNode() = default;

    FatherNode(const FatherNode& node) : ttNode(node) {
        for (const auto &son : node.sons_) {
            sons_.emplace_back(new SonNode(*son));
        }
    }
    base* clone() const override {
        return new FatherNode(*this);
    }

private:
    std::vector<SonNode*> sons_;
};

class otherNode : public base {
public:
    otherNode() : base() {}
    ~otherNode() = default;
    base* clone() const override { return new otherNode(*this); }
    otherNode(const otherNode& node) : base(node) {
        ttt = dynamic_cast<ttNode*>(node.ttt->clone());
    }
private:
    ttNode* ttt;
};


TEST_F(tt, base1) {
    base *o = new otherNode();
    base *f = new FatherNode();
    base *o1 = o->clone();
    base *f1 = f->clone();
    delete o1;
    delete f1;
}

我不能使用,因为ttNode是抽象类。ttt = new ttNode(*node.ttt);

C++ 设计模式 克隆 复制构造函数 原型模式

评论

1赞 john 4/10/2023
我不明白的目的。它不添加任何内容,如果您将其删除并改用,则它会消失。ttNodebasedynamic_cast
0赞 fana 4/10/2023
为什么要使用返回类型进行覆盖?您可以使用派生类型(例如)作为返回类型进行覆盖。因此,更改 so(并将此类覆盖添加到 ),则不需要。base*clonecloneFatherNode*clonettNodedynamic_cast

答:

0赞 Red.Wave 4/10/2023 #1

您对原始指针的大量使用使代码难以维护。当前代码段包含大量内存泄漏。除了原始指针的问题之外,还可以根据协变返回类型和/或 CRTP 来回答这个棘手的问题。从 C++20 开始,CRTP 可以使用推导的这个参数来暗示:

class base {
public:
    explicit base() {}
    virtual ~base() = default;
    auto static_clone(this const auto &self) { return std::make_unique<std::remove_cvref_t<decltype(self)>(self);};
};

最终将为每个派生类型创建正确类型的唯一指针。CRTP与协变返回类型的组合是我还没有尝试过的;这似乎很复杂,特别是如果我们想尝试使用智能指针进行安全测试。 但现在你有两条不同的路线可以遵循:协变返回和/或 CRTPstatic_clone