具有派生 class 的 C++ 共享指针

C++ shared pointer with derived class

我正在尝试从派生 class 获取基 class 的共享指针。这是代码:

class Base {
    public:
    typedef std::shared_ptr<Base> Ptr;
    Base();
    Base(const Base& orig);
    virtual Ptr getShared() = 0;
};


class Derived : public Base {
    public:
    // default constructor and copy constructor
    virtual Base::Ptr getShared() {
        return std::make_shared<Derived>(this);
    }
};

我正在尝试使用它来获取 Base::Ptr 的向量,如下所示:

std::vector<Base::Ptr> objects;
Derived d;
objects.push_back(d.getShared()); 

我 运行 遇到了复制构造函数的问题,我知道这与通过在幕后尝试将指针转换为 ref 来破坏常量正确性有关。我只是无法确定原因是什么,或者我做出了错误的假设。有什么想法吗?

Base.h:20:5: note: no known conversion for argument 1 from 'Base*' to 'const Base&' Base.h:19:5: note: candidate: Base::Base()

编辑: Severin 的回答使我找到了针对这个特定问题的正确解决方案。 Sahu 的回答是正确的,但我试图让多个对象共享一个指向单个对象的指针。 enable_shared_from_this 如果您需要对同一对象的多个引用而不构造其他实例,则可以采用这种方法。问题在于,第一次在指针上调用 make_shared 会达到您的预期,但使用同一指针的后续调用会使用该指针作为构造函数的参数来构造该对象的其他实例。 enable_shared_from_this 的正确用法将代替 return 一个 shared_ptr,它与引用该对象的所有其他 shared_ptr 共享访问权限。

编辑2:为了完整起见,这种情况实际上是由于误解了引用传递和指针传递之间的区别造成的。在这个 特殊的 案例中,真正的问题是应用程序其他地方的设计决策。为其他有类似问题的人提供食物。

std::make_shared(直到 C++17)的签名是

template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );

它将构造一个 T 类型的对象,在其周围包裹一个 shared_ptr 并 return shared_ptr。详情见 http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared

使用

    return std::make_shared<Derived>(this);

无效,因为您不能从 Derived* 构造类型 Derived 的对象。您需要将该行更改为:

    return std::make_shared<Derived>(*this);

它return是一个shared_ptr,它包装了一个新复制构造的Derived对象。

问题出在这一行:

virtual Base::Ptr getShared() {
    return std::make_shared<Derived>(this);
}

Base::Ptr 的类型是 std::shared_ptr<Base>.
std::make_shared<Derived>(this) 将 return 一个 std::shared_ptr<Derived>

即使 Derived 继承自 Basestd::shared_ptr 是模板化的 class,而 shared_ptr<Derived> 不是 [=31] =] 继承自 shared_ptr<Base>

你想要的是return正确的共享指针:

virtual Base::Ptr getShared() {
    return std::shared_ptr<Base>(this);
}