Clone pattern for std::shared_ptr in C++

后端 未结 1 726
遇见更好的自我
遇见更好的自我 2020-12-19 20:59

Why do you need (in order to make it compile) the intermediate CloneImplementation and std::static_pointer_cast (see Section 3 bel

相关标签:
1条回答
  • 2020-12-19 21:46

    The general rule in C++ is that the overriding function must have the same signature as the function it overrides. The only difference is that covariance is allowed on pointers and references: if the inherited function returns A* or A&, the overrider can return B* or B& respectively, as long as A is a base class of B. This rule is what allows Section 1 to work.

    On the other hand, std::shared_ptr<Derived> and std::shared_ptr<Base> are two totally distinct types with no inheritance relationship between them. It's therefore not possible to return one instead of the other from an overrider. Section 2 is conceptually the same as trying to override virtual int f() with std::string f() override.

    That's why some extra mechanism is needed to make smart pointers behave covariantly. What you've shown as Section 3 is one such possible mechanism. It's the most general one, but in some cases, alternatives also exist. For example this:

    struct Base {
        std::shared_ptr< Base > Clone() const {
            std::cout << "Base::Clone\n";
            return std::shared_ptr< Base >(CloneImplementation());
        }
    
    private:
        virtual Base* CloneImplementation() const {
            return new Base(*this);
        }
    };
    
    struct Derived : public Base {
         std::shared_ptr< Derived > Clone() const {
            std::cout << "Derived::Clone\n";
            return std::shared_ptr< Derived >(CloneImplementation());
        }
    
    private:
        virtual Derived* CloneImplementation() const override {
            std::cout << "Derived::CloneImplementation\n";
            return new Derived(*this);
        }
    };
    
    0 讨论(0)
提交回复
热议问题