假设DerivedClass
来自BaseClass
以下是否有效?
boost::shared_ptr<BaseClass> a(new BaseClass());
boost::shared_ptr<DerivedClass> b(new DerivedClass());
a=b;
遵循此question,我了解现在a
指向派生的和b
点到基地(对吧?)
此外,现在如果我通过a
调用一个函数,它会调用派生的实现吗?
答案 0 :(得分:13)
...
a=b;
您正在重新分配到a
,因此a
和 b
现在都会指向DerivedClass
对象。 BaseClass
对象将被销毁,因为此时它的引用计数将为零(由于a
被重新分配以指向不同的对象)。
由于a
现在指向DerivedClass
对象,虚拟函数调用(在BaseClass
中定义并在DerivedClass
中覆盖)通过a
将调用相应的DerivedClass
中的成员函数。
当a
和b
都超出范围时,DerivedClass
对象将被销毁。
如果您需要通过a
访问特定于派生类的函数(例如,DerivedClass
中的非虚函数),您可以使用:
boost::dynamic_pointer_cast<DerivedClass>(a)->SomeFunctionOnlyInDerivedClass();
当然这只是一个简洁的例子,展示了用法。在生产代码中,您几乎肯定会在取消引用指针之前测试成功转换为DerivedClass
。
答案 1 :(得分:4)
假设
DerivedClass
来自BaseClass
。以下是否有效?
是。正如
没有任何问题boost::shared_ptr<BaseClass> pbase(new DerivedClass());
(假设在两种情况下BaseClass都有一个虚拟析构函数。)智能指针的设计尽可能像普通指针一样,并提供与BaseClass* pbase = new DerivedClass();
相同的行为,以及所有生命周期管理善。
根据这个问题,我了解现在
a
指向派生的和b
点到基地(对吗?)
不,a和b都指向DerivedClass实例。链接文章引用的交换发生在 operator = 内的临时对象上。当该临时对象超出范围时,将删除BaseClass实例。
此外,现在如果我通过
a
调用一个函数,它会调用派生的实现吗?
是。如果你看一下 operator-&gt; 的实现,它所做的就是返回指向基本 operator-&gt; 的指针:
T * operator-> () const // never throws
{
BOOST_ASSERT(px != 0);
return px;
}
这样行为与普通指针相同。
答案 2 :(得分:3)
当做a = b时,你告诉a指向对象b也指向。所以你调用的所有方法,你调用对象b的BaseClass部分都指向。
因此,如果它包含在DerviedClass中覆盖的虚方法,则会调用覆盖的版本。