0

I want to get shared_ptr from this of derived class.
std::enable_shared_ptr_from_this inherited by base class and gets std::shared_ptr<Base>, but not std::shared<Derived>. I can use std::reinterpret_pointer_cast or std::dynamic_pointer_cast but

  1. is so much code
  2. is it safe when multiple inheritance used?
    Or it is the only way?

Example code:

class Base : public std::enable_shared_from_this<Base> {

};

class Derived : public Base {
public:
    std::shared_ptr<Derived> GetPointer() const {
        return shared_from_this(); // but it returns std::shared<Base> type
    }
};

Thanks in advance!

georg774
  • 15
  • 3
  • I think you more or less answered your own question. You can use `std::static_pointer_cast`, since you know the exact type there's no need for a dynamic cast. Using "is so much code" as an argument not to do something the right way is basically always a bad excuse. And in this case, there's no other way, if you don't do the cast, the code won't compile. So yes, it's safe and the only way. Also, it's hardly a lot of extra code. It's maybe 30 extra characters inside 1 function... – AVH Oct 29 '20 at 12:50

1 Answers1

2

It's perfectly fine and safe to do it the way you're currently doing.

#include <memory>

class Base : public std::enable_shared_from_this<Base>{
public:
    virtual int32_t getid() = 0;
};
class Derived : public Base{
public:
    int32_t id;
    Derived(int32_t id){
        this->id = id;
    }
    ~Derived(){
        
    }
    int32_t getid(){
        return id;
    }
};
int main(){
    std::shared_ptr<Derived> child = std::make_shared<Derived>(1033);
    std::shared_ptr<Base> parent = child;//This needs no extra work
    std::shared_ptr<Derived> secondchildinstance = std::static_pointer_cast<Derived>(parent);//this needs casting
    if(secondchildinstance!=nullptr){
        //shared_from_this can be called directly from the child without an explicit method
        std::shared_ptr<Base> secondparentinstance = secondchildinstance->shared_from_this();
        
        //shared_from_this would require downcasting to get the child
        std::shared_ptr<Derived> thirdchildinstance =  std::static_pointer_cast<Derived>(secondchildinstance->shared_from_this());//requires casting
        
        if(thirdchildinstance!=nullptr){
            printf("use count:%ld id:%d",thirdchildinstance.use_count(),thirdchildinstance->getid());
        }
    }
    return 0;
}

You probably could make your job for down-casting from parent to child easier through a wrapper method.

Something to note is, you do not need an explicit method in order to call shared_from_this, because the parent already inherits it you can call the child->shared_from_this() directly but it will give the shared instance of the base class which will need downcasting.

Irelia
  • 3,407
  • 2
  • 10
  • 31
  • There's no need for an "expensive" dynamic cast here. You know the exact type of the pointer, so a static cast is fine. – AVH Oct 29 '20 at 12:51
  • How expensive is dynamic_pointer_cast compared to static_pointer_cast? Is static compile time? – Irelia Oct 29 '20 at 12:54
  • You did not complete his example. `std::shared_ptr GetPointer() const { return std::static_pointer_cast(shared_from_this()); }` Why does this not compile with dynamic_pointer_cast, but with static? I'm curious. – lars Oct 29 '20 at 12:57
  • I'll make the change – Irelia Oct 29 '20 at 12:58
  • @Nina The cost of a static_cast is very low, see also 2nd comment in accepted answer here: https://stackoverflow.com/questions/6445841/c-static-cast-runtime-overhead A dynamic_cast has significant overhead. – lars Oct 29 '20 at 13:04