c++11 - C++中std::shared_ptr的克隆模式

标签 c++11 overriding clone smart-pointers virtual-functions

为什么需要(为了使其编译)中间CloneImplementationstd::static_pointer_cast(请参见下面的 3 部分)对std::shared_ptr使用克隆模式,而不是更接近(请参见下面的 2 部分)来使用原始指针(请参阅下面的部分1 )?因为据我所知,std::shared_ptr具有通用的复制构造函数和通用的赋值运算符?

1.带有原始指针的克隆模式:

#include <iostream>

struct Base {
    virtual Base *Clone() const {
        std::cout << "Base::Clone\n";
        return new Base(*this);
    }
};

struct Derived : public Base {
    virtual Derived *Clone() const override {
        std::cout << "Derived::Clone\n";
        return new Derived(*this);
    }
};

int main() {
  Base *b = new Derived;
  b->Clone();
}

2.带有共享指针的克隆模式(天真尝试):
#include <iostream>
#include <memory>

struct Base {
    virtual std::shared_ptr< Base > Clone() const {
        std::cout << "Base::Clone\n";
        return std::shared_ptr< Base >(new Base(*this));
    }
};
struct Derived : public Base {
    virtual std::shared_ptr< Derived > Clone() const override {
        std::cout << "Derived::Clone\n";
        return std::shared_ptr< Derived >(new Derived(*this));
    }
};

int main() {
  Base *b = new Derived;
  b->Clone();
}

输出:
error: invalid covariant return type for 'virtual std::shared_ptr<Derived> Derived::Clone() const'
error:   overriding 'virtual std::shared_ptr<Base> Base::Clone() const'

3.带有共享指针的克隆模式:
#include <iostream>
#include <memory>

struct Base {

    std::shared_ptr< Base > Clone() const {
        std::cout << "Base::Clone\n";
        return CloneImplementation();
    }

private:

    virtual std::shared_ptr< Base > CloneImplementation() const {
        std::cout << "Base::CloneImplementation\n";
        return std::shared_ptr< Base >(new Base(*this));
    }
};
struct Derived : public Base {

    std::shared_ptr< Derived > Clone() const {
        std::cout << "Derived::Clone\n";
        return std::static_pointer_cast< Derived >(CloneImplementation());
    }

private:

    virtual std::shared_ptr< Base > CloneImplementation() const override {
        std::cout << "Derived::CloneImplementation\n";
        return std::shared_ptr< Derived >(new Derived(*this));
    }
};

int main() {
  Base *b = new Derived;
  b->Clone();
}

最佳答案

C++中的一般规则是,覆盖函数必须与其覆盖的函数具有相同的签名。唯一的区别是指针和引用允许协方差:如果继承的函数返回A*A&,则重写器可以分别返回B*B&,只要AB的基类。该规则使Section 1 可以正常工作。

另一方面,std::shared_ptr<Derived>std::shared_ptr<Base>是两个完全不同的类型,它们之间没有继承关系。因此,不可能从替代程序返回一个而不是另一个。 2节在概念上与尝试使用virtual int f()覆盖std::string f() override相同。

这就是为什么需要一些额外的机制来使智能指针行为协变的原因。您显示为部分3 的部分就是这样一种可能的机制。它是最通用的一种,但在某些情况下,也存在替代方法。例如:

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

关于c++11 - C++中std::shared_ptr的克隆模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43586090/

相关文章:

c# - 在 C# : deep or shallow copy? 中实现 ICollection.CopyTo

JQuery 循环克隆

c++ - 如何避免相似模板中的代码重复

c++ - 在自己的构造中使用对象有什么问题吗?

c++ - Visual Studio Code 中无法识别的 token C/C++(7) 错误

java - 为什么在覆盖该方法时调用父类(super class)方法? (来自OCA练习测试)

spring-mvc - Spring MVC application.properties 未被配置文件 application-dev.properties 覆盖

module - 如何覆盖 PrestaShop 1.7.7 模块类?

jquery - 克隆表格 不带克隆输入值

c++ - 从模板基类派生