boost::shared_ptr和派生类的赋值问题

7
假设DerivedClass是从BaseClass派生的
以下代码是否可行?
boost::shared_ptr<BaseClass> a(new BaseClass());
boost::shared_ptr<DerivedClass> b(new DerivedClass());
a=b;

根据这个问题,我理解现在a指向派生类,而b指向基类(对吗?)

那么,如果我通过a调用函数,它会调用派生类的实现吗?

3个回答

13
...
a=b;

你正在重新分配 a 的值,因此现在 a b 都将指向 DerivedClass 对象。此时,BaseClass 对象的引用计数将为零(因为 a 被重新指向了一个不同的对象),因此它将被销毁。

由于 a 现在指向一个 DerivedClass 对象,因此通过 a 调用虚函数(在 BaseClass 中定义并在 DerivedClass 中重载)将调用 DerivedClass 中相应的成员函数。

ab 都超出其作用域时,DerivedClass 对象将被销毁。

如果需要通过 a 访问派生类特定的函数(例如 DerivedClass 中的非虚函数),可以使用:

boost::dynamic_pointer_cast<DerivedClass>(a)->SomeFunctionOnlyInDerivedClass();
当然,这只是一个简洁的示例来展示使用。在实际生产代码中,您几乎肯定会在取消引用指针之前测试对DerivedClass的成功强制转换。

1
一个 static_pointer_cast 也可以工作,因此成为在 DerivedClass 中调用非虚函数的首选方式,你觉得呢?boost::static_pointer_cast<DerivedClass>(a)->SomeFunctionOnlyInDerivedClass(); - j00hi

4
假设DerivedClass派生自BaseClass,下面的代码是否可以正常工作?
是的。就像下面的代码没有问题一样:
boost::shared_ptr<BaseClass> pbase(new DerivedClass());

(假设在这两种情况下BaseClass都有一个虚拟析构函数。)智能指针的设计是尽可能像普通指针一样行为,并提供与BaseClass * pbase = new DerivedClass();相同的行为,以及所有生命周期管理的好处。

根据这个问题,我理解现在a指向派生类,b指向基类(对吗?)

不,a和b都将指向DerivedClass实例。链接文章中提到的交换发生在operator=内部的临时对象上。当该临时对象超出作用域时,BaseClass实例将被删除。

此外,现在如果我通过a调用函数,它会调用派生实现吗?

是的。如果您查看operator->的实现,它所做的就是返回应调用基本operator->的指针:

T * operator-> () const // never throws
{
    BOOST_ASSERT(px != 0);
    return px;
}

这样做的目的是使行为与普通指针相同。


3

当执行a=b时,你是在告诉a指向b所指向的对象。因此,你调用的所有方法都是在对象b所指向的BaseClass部分上调用。

因此,如果它包含一个在DerivedClass中被覆盖的虚拟方法,则会调用被覆盖的版本。


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