考虑以下大纲:
class Base { /* ... */ };
class Derived : public Base
{
public:
void AdditionalFunctionality(int i){ /* ... */ }
};
typedef std::shared_ptr<Base> pBase;
typedef std::shared_ptr<Derived> pDerived;
int main(void)
{
std::vector<pBase> v;
v.push_back(pBase(new Derived()));
pDerived p1( std::dynamic_pointer_cast<Derived>(v[0]) ); /* Copy */
pDerived p2 = std::dynamic_pointer_cast<Derived>(v[0]); /* Assignment */
p1->AdditionalFunctionality(1);
p2->AdditionalFunctionality(2);
/* A */
return 0;
}
在这里,我使用添加功能(AdditionalFunctionality
方法)的派生类来扩展基类。
第一个问题,这样好吗?我读过很多问题说这不好,您应该在基类中声明附加功能(通常建议在基类中将它们设为纯虚拟方法)。但是,我不想这样做。我想扩展基类的功能,而不仅仅是以不同的方式实现它。有没有更好的解决方案来实现这个目标?
好的,所以在这段代码中,我还使用 STL 容器来存储这些指针,这允许我存储指向 Base 类型对象和 Derived 类型对象的指针,而无需对对象进行切片。
第二个问题,这是有道理的,对吧?实际上,我是通过使用指向基类对象的指针而不是基类对象本身来避免切片?
如果我“知道”某个指针指向 Derived 对象,那么我会使用它std::dynamic_pointer_cast
来强制转换智能指针。
第三个问题,这个编译没有警告并且可以工作,但是它安全吗?有效的?它会破坏共享指针的引用计数方面并在我预期之前失败到delete
我的对象或它们吗?delete
最后,我可以使用复制构造函数或通过赋值来执行此转换,如 p1 和 p2 所示。有没有首选/正确的方法?
类似的问题:
- 将 shared_ptr<Base> 向下转换为 shared_ptr<Derived>?:这非常接近,但是衍生类没有像我的那样添加额外的功能,所以我不确定它是否完全一样。此外,它使用
boost::shared_ptr
我正在使用的地方std::shared_ptr
(尽管我理解 boost 将 shared_ptr 捐赠给了 std 库,所以它们可能是相同的)。
谢谢您的帮助。
编辑:
我问的一个原因是我意识到可以(错误地)执行以下操作:
/* Intentional Error */
v.push_back(pBase(new Base()));
pDerived p3( std::dynamic_pointer_cast<Derived>(v[1]) );
p3->AdditionalFunctionality(3); /* Note 1 */
我尝试将指向 Base 对象的指针向下转换为 Derived 对象的指针,然后调用仅在 Derived 类中实现的方法。换句话说,指向的对象没有定义(或者甚至没有“意识到”该方法)。
这不会被编译器捕获,但可能会导致段错误,具体取决于AdditionalFunctionality
定义方式。