Downcasting shared pointer to derived class with additional functionality - is this safe?

前端 未结 3 735
时光取名叫无心
时光取名叫无心 2021-02-05 19:23

Consider the following outline:

class Base { /* ... */ };

class Derived : public Base
{
public:
    void AdditionalFunctionality(int i){ /* ... */ }
};

typedef         


        
相关标签:
3条回答
  • 2021-02-05 19:55

    OK, first off, if you do this, you'll want to make sure that Base has a virtual destructor. Otherwise, you'll get undefined behavior when the vector goes out of scope. (The vector's destructor will call Base's destructor for each of its elements. If any elements are really a Derived -- KABOOM!) Other that that, what you've written is perfectly safe and valid.

    But what's the point? If you have a container of objects, you want to be able to treat them all the same. (Loop over all of them and invoke a function on each, or whatever.) If you didn't want to treat them the same, why put them in one container? So you've got a vector that can hold pointers to Base or pointers to Derived -- how do you know which elements are of which type? Are you planning to just call dynamic_cast on each element every time you want to call AdditionalFunctionality to check to make sure that the element really points to a Derived? That's neither efficient nor idiomatic, and it basically defeats the whole point of using inheritance. You might as well just be using a tagged union.

    You're using the wrong tool for the job. When people told you not to do this, it wasn't because it was unsafe or invalid, it's because you'll just end up making your code more complex than it needs to be.

    0 讨论(0)
  • 2021-02-05 20:07

    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.

    0 讨论(0)
  • 2021-02-05 20:10

    If the container should never have base objects in it (I can't tell from the question but that's implied by your edit) then you should make the container hold derived objects instead, and then you have automatic access to the additional function.

    If the container can have both types of objects, then it seems that you want to be able to treat all the objects as the base class within that container. In this case you almost certainly want to use polymorphism to do the right thing: Have a virtual interface that basically says "Do this work" and the parent version may do nothing at all. Then the child version of the method implements the additional functionality you need.

    I think you may have a code smell that your objects are less related than you think. Are you inheriting to reuse, or to allow substitution? You may also want to reconsider what your public interface looks like.

    All that said, should you decide to continue with your current design (which I would at least strongly review) I think your downcasting should be safe as long as you check the result of the dynamic cast for non-null before using it.

    0 讨论(0)
提交回复
热议问题