std::static_pointer_cast与static_cast<std::shared_ptr<A>>的区别

7

我有一个类层次结构,其中BA继承,如下所示:

class A : public std::enable_shared_from_this<A>
{

};

class B : public A
{
   void f()
   {
        // the code below compiles
        std::shared_ptr<B> copyOfThis = std::static_pointer_cast<B>(shared_from_this()); 
        // the code below does not
        std::shared_ptr<B> copyOfThis = static_cast<std::shared_ptr<B>>(std::make_shared<A>(shared_from_this()));
}
};

实际上,我想了解为什么不能使用 static_cast 将父类的 shared_ptr 转换为子类的 shared_ptr,即使它实际上包含了子类的 this

编辑:请参考此问题:Polymorphic smart pointer usage。在这里,我询问为什么可以在父类的共享指针上强制转换子类的共享指针。答案是有一个模板构造函数。详情请参见问题描述。那么为什么即使shared_ptr<A>shared_ptr<B>之间没有关系,这个构造函数也不能用于转换呢?


你的问题是什么?你展示的这两行代码尝试做完全不同的事情。第二行代码分配了一个新对象,而第一行只创建了一个指向当前对象的共享指针。 - interjay
std::make_shared 分配一个新的托管对象,与 *this 不同。 - interjay
std::make_shared<A>(shared_from_this()) 是用来干什么的?你有尝试编译这段代码吗?这可能会回答你的问题。 - Jonathan Wakely
@JonathanWakely 它只在Xcode上编译。 - Narek
3
“那么为什么这个构造函数没有用呢?”- 因为你现在是在反过来做。 B * 可以隐式转换为 A *,但是 A * 不能隐式转换为 B *。因此,构造函数不参与重载决议。 - 5gon12eder
显示剩余4条评论
2个回答

11

由于类之间不存在继承关系,因此无法将 shared_ptr<A> 强制转换为 shared_ptr<B>。出于同样的原因,也无法将 vector<A> 强制转换为 vector<B>

使用相关类型实例化类模板并不会使模板实例化相关。

shared_ptr<T>(const shared_ptr<Y>&) 构造函数没有帮助,因为它仅在 Y* 隐式转换为 T* 时可用,即它是为了支持与隐式发生的相同指针转换(例如B*A*),而不是 A*B*

你可以这样做:

shared_ptr<A> thisA = shared_from_this();
shared_ptr<B> thisB(thisA, static_cast<B*>(thisA.get()));

这将创建一个shared_ptr<B>,它与thisA共享所有权,并持有指针static_cast<B*>(thisA.get())

static_pointer_cast<B>(thisA)正是如此,但以上使用的别名构造函数是在稍后添加到shared_ptr中的,因此在发明static_pointer_cast时不存在,而且它执行的操作也不太清楚。 static_pointer_cast更加表达清晰。如果想对指针类型进行静态转换,请使用static_pointer_cast


你看过我对问题的“编辑”了吗? - Narek
唯一将没有关系的类之间进行 static_cast 的方法,就是使用转换运算符。 - MarkusAtCvlabDotDe
@ Narek,是的,请查看更新后的答案,并阅读您所问的构造函数的文档!还要阅读您其他问题的答案! - Jonathan Wakely
所以,如果我理解正确的话,唯一的原因就是上转型。 - Narek
@MarkusAtCvlabDotDe 转换运算符和构造函数也是如此。 - Narek

7
长话短说:std::shared_ptr<A>不是std::shared_ptr<B>的父类。这就是static_pointer_cast存在的全部意义。

@AnkitAcharya。他所说的不是A类和B类,而是两个不同的泛型类std::shared_ptr<A>和std::shared_ptr<B>,它们确实是完全不同的类。 - MarkusAtCvlabDotDe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接