Prototype Design Pattern Example in C++

81 views Asked by At

I am learning prototype design pattern and implementing a demo,I add deep copy constructors and clone functions to these classes,but I'm not sure if I implemented them correctly. I did the dynamic_cast conversion in otherNode, It‘s a little weird. Any suggestions?

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;
}

I can't use ttt = new ttNode(*node.ttt); because ttNode is abstract class.

1

There are 1 answers

0
Red.Wave On

Your extensive use of raw pointers has made the code hard to maintain. And current snippet contains lots of memory leaks. Aside from the problem with raw pointers, the cannonical question can be answered in terms of covariant return types and/or CRTP. since C++20, CRTP can be implied using deduced this argument:

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);};
};

The static_clone will eventually create correct type of unique pointer for each derived type. Combination of CRTP with covariant return type is what I have not tried yet; it seems to be complex, particularly if we want to try safty using smart pointers. But now you have two different routes to follow: covariant return and/or CRTP.