将共享指针转换为带有附加功能的派生类 - 这是安全吗? [英] Downcasting shared pointer to derived class with additional functionality - is this safe?

查看:96
本文介绍了将共享指针转换为带有附加功能的派生类 - 这是安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下大纲:

  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])); / *复制* /
pDerived p2 = std :: dynamic_pointer_cast< Derived>(v [0]); / *赋值* /

p1-> AdditionalFunctionality(1);
p2-> AdditionalFunctionality(2);

/ * A * /

return 0;
}

这里我使用派生类扩展基类, AdditionalFunctionality 方法)。



第一个问题,我读了很多问题,说这不行,你应该声明基类中的附加功能(通常建议使它们在基类中的纯虚拟方法)。但是,我不想这样做。我想扩展基类的功能,而不只是实现它不同。是否有更好的解决方案来实现这个目标?



好吧,所以在这段代码中,我也使用STL容器来存储这些指针,这允许我存储指针



第二个问题,这很有意义,对吗?我实际上是通过使用指向基类对象而不是基类对象本身的指针来避免切片?



如果我知道某个指针是一个派生对象,然后使用 std :: dynamic_pointer_cast 来强制转换智能指针。



第三个问题,警告和工程,但它是安全吗?有效?它会破坏共享指针的引用计数方面,并且未能在我预期之前删除我的对象或 delete / p>

最后,我可以使用复制构造函数或通过如p1和p2所示的赋值来执行此转换。这是否有首选/正确的方法?



类似问题:




  • 向下转换shared_ptr< Base>到shared_ptr< Derived> ;? :这是非常接近,但是dervied类不添加像我的附加功能,所以我不确定它是完全一样的。此外,它使用 boost :: shared_ptr 其中我使用 std :: shared_ptr (虽然我理解boost捐赠shared_ptr到std库,因此它们可能是相同的)。



感谢您的帮助。






编辑



意识到以下可以完成(不正确):

  / *故意错误* / 
v.push_back (new Base()));
pDerived p3(std :: dynamic_pointer_cast< Derived>(v [1]));
p3-> AdditionalFunctionality(3); / *注1 * /

我试图将一个指针一个Derived对象,然后调用只在Derived类中实现的方法。换句话说,指向的对象没有定义(或者甚至不知道该方法)。



这不是由编译器捕获的,

解决方案 可能会导致segfault根据 AdditionalFunctionality / div>

Base 是否有虚拟析构函数?如果是,那么使用向下转换是安全的。在您的错误示例 pDerived 中应该在结果中 NULL ,因此您需要检查 dynamic_pointer_cast


Consider the following outline:

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;
}

Here I'm extending the base class with a derived class that adds functionality (the AdditionalFunctionality method).

First question, is this OK? I've read a lot of questions that say this is not okay and you should declare the additional functionality in the base class (often suggested as making them pure virtual methods in the base class). However, I don't want to do this. I want to extend the functionality of the base class, not just implement it differently. Is there a better solution to accomplish this goal?

Okay, so in this code I am also using an STL container to store these pointers which allows me to store pointers to both objects of type Base as well as objects of type Derived without slicing the objects.

Second question, this makes sense, right? I am, in fact, avoiding slicing by using pointers to base class objects rather than the base class objects themselves?

If I "know" that a certain pointer is to a Derived object, I then use std::dynamic_pointer_cast to cast the smart pointer.

Third question, this compiles without warning and works, but is it safe? Valid? Will it break the reference counting aspect of shared pointers and fail to delete my objects or delete them before I expect?

Lastly, I can do this cast using either the copy constructor or via assignment as shown for p1 and p2. Is there a preferred / correct way of doing this?

Similar questions:

  • Downcasting shared_ptr<Base> to shared_ptr<Derived>? : This is very close, however the dervied class does not add additional functionality like mine does, so I'm not sure it's completely the same. Also, it uses boost::shared_ptr where I'm using std::shared_ptr (although I understand boost donated shared_ptr to the std library, so they're likely the same).

Thank you for your help.


Edit:

One reason I ask is that I realize that the following could be done (incorrectly):

    /* Intentional Error */
    v.push_back(pBase(new Base()));
    pDerived p3( std::dynamic_pointer_cast<Derived>(v[1]) );
    p3->AdditionalFunctionality(3); /* Note 1 */

Where I attempt to downcast a pointer to a Base object to a pointer of a Derived object and then call a method that is only implemented in the Derived class. In other words, the object pointed to doesn't define (or isn't even "aware of" the method).

This is not caught by the compiler, but may cause a segfault depending on how AdditionalFunctionality is defined.

解决方案

Does the Base has a virtual destructor? If yes then it is safe to use downcasting. In your incorrect sample pDerived should be NULL in result, so you need to check the result of dynamic_pointer_cast every time.

这篇关于将共享指针转换为带有附加功能的派生类 - 这是安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆