C ++与派生类共享指针

时间:2018-01-05 03:57:10

标签: c++ c++11 pointers shared-ptr

我试图从派生类中获取基类的共享指针。这是代码:

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

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

  

Base.h:20:5:注意:没有已知的转换参数1来自&#39; Base *&#39;   to&#39; const Base&amp;&#39; Base.h:19:5:注意:候选人:Base :: Base()

编辑: Severin的回答让我找到了解决这一特定问题的正确方法。 Sahu的回答是正确的,但我试图让多个对象共享一个对象的指针。 enable_shared_from_t这是你需要多次引用同一个对象而不构造其他实例的方法。问题是第一次在指针上调用make_shared会达到预期效果,但后续使用相同指针的调用使用指针作为构造函数的参数构造该对象的其他实例。正确使用enable_shared_from_this将返回一个shared_ptr,该shared_ptr与引用该对象的所有其他shared_ptrs共享访问权。

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

2 个答案:

答案 0 :(得分:1)

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

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

它将构造一个T类型的对象,在其周围包裹shared_ptr并返回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);

它返回一个shared_ptr,它包装一个新复制的Derived对象。

答案 1 :(得分:0)

问题出在这一行:

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

Base::Ptr的类型为std::shared_ptr<Base> std::make_shared<Derived>(this)将返回std::shared_ptr<Derived>

即使Derived继承自Basestd::shared_ptr是一个模板化的类,shared_ptr<Derived> 继承自shared_ptr<Base>

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

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