LibertyPaul
LibertyPaul

Reputation: 1167

Get non-const reference from dynamic_cast

Is it possible to get reference to base class pointer from dynamic cast?

#include <cassert>

class A{
public:
    virtual ~A(){}
};

class B : public A{};


int main(){
    A *a = new B;

    B *&b = dynamic_cast<B *>(a);

    // work with pointer as of type B

    b = new B; // this should change a aswell

    assert(a == b);
}

This code isn't being compiled with error invalid initialization of non-const reference of type 'B*&' from an rvalue of type 'B*'

Upvotes: 2

Views: 413

Answers (2)

Kerrek SB
Kerrek SB

Reputation: 476970

The value category of any cast expression depends on the destination type of the cast:

  • Destination type is non-reference (T): prvalue
  • Destination type is lvalue-reference (T&): lvalue
  • Destination type is rvalue-reference (T&&): xvalue

Since your destination type is B*, a non-reference, the result of the cast is a prvalue, which cannot bind to a mutable lvalue reference.

If you're trying to replace the most-derived object of which *a is a subobject, you could try something like this:

assert(typeid(*a) == typeid(B));
void* addr = dynamic_cast<void*>(a);
::new (addr) B;

Note that this fails to run the destructor, so if your code depends on the side effects of the destructor, the behaviour is undefined. You can run the destructor yourself first, though:

a->~A();                     // if A::~A is virtual
dynamic_cast<B*>(a)->~B();   // otherwise

Upvotes: 1

songyuanyao
songyuanyao

Reputation: 172894

No, you can't.

dynamic_cast<B *>(a); will convert a with type A* to B*, it will construct a temporary of type B* and return it. Temporary variable can't be bount to non-const lvalue reference. It might be bound to const reference but you can't change it later on as you want.

Upvotes: 3

Related Questions