4

I was playing around with a bunch of casting operators a while ago, which apparently I did not really get at the time. I was looking over my code now and I saw this:

Base(Derived &p_derived) : m_state(static_cast<Base>(p_derived).m_state){}

I think I have now got a better understanding of casting of pointers and references thanks to a very good answer here on stackoverflow, but now there's objects involved. What exactly happens when the reference is casted to an object? Or what if p_derived was the object itself and not just a reference? Would it be creating new objects and if so, how would these be instanciated?

I'm also surprised that this could be compiled at all since in Base.h, where this code is found, Derived is only forward declared meaning it shouldn't know that it actually derives from Base. I tried at another place to do a static cast from a Derived* to a Base*, but that would rightfully not compile due to the types being incompatible as far as that translation unit was concerned.

Community
  • 1
  • 1
user1130005
  • 392
  • 1
  • 4
  • 15

1 Answers1

10

When you use a reference, you're generally actually using the object it refers to. That's the magic transparency of reference syntax that you don't get with pointers; arguably it's their reason for being.

This scenario is no exception: you're taking the p_derived referee and constructing a new Base out of it via slicing.

static_cast<Base&>(p_derived) will cast the reference itself, if that's what you're after (and even if it's not :P).

I'm also surprised that this could be compiled at all since in Base.h, where this code is found, Derived is only forward declared meaning it shouldn't know that it actually derives from Base.

Yea, that surprises me, too. Are you sure? (Demo / Demo - not sure which you're using)

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • So you're saying that "static_cast(d)", whether d is a reference or the object, is essentially the same as "Base b; b = d;" in this case? And no, it's more like this: http://codepad.org/8bn2MxAl – user1130005 Jan 17 '12 at 10:10
  • @user1130005: That's exactly what I'm saying. What are you trying to achieve with that code? Why not `m_state(static_cast(p_derived.m_state.get()))` or similar? – Lightness Races in Orbit Jan 17 '12 at 10:21
  • Yes, I should definitely solve it differently. I got several classes deriving from Base which serves as sort of an interface to a shared state among the deriving classes, that's why I need to pass in an object (perhaps Base& would be better) to get its state which is private to Base. I'm trying to turn Java code to C++, and Java allows all kinds of crazy dependencies. That's why I'm getting these problems. I'm still curious though as to why the static_cast was allowed at all. Is it allowed in C++ to do "A a; B b; a = b;" even though A and B has nothing in common? – user1130005 Jan 17 '12 at 10:47
  • Only if the types are compatible in some way. As I said in my answer, I don't really believe that your code compiled. – Lightness Races in Orbit Jan 17 '12 at 10:49
  • Yes, you did sort of imply that. Sorry that I didn't reply to that directly, but here it is: It does in fact compile. http://codepad.org/WeXkKovO (It's actually a shared_ptr, but codepad didn't seem to like that) – user1130005 Jan 17 '12 at 11:00
  • @user1130005: Ah, but even though there's no inheritance, `Base` can be constructed from a `Derived&`... that very constructor is the one that makes it so! I wonder whether you have some infinite recursion in that initialiser as a consequence. – Lightness Races in Orbit Jan 17 '12 at 11:08
  • Ah, of course! Thank you. Yes, I haven't tried running it but it may very well take a bad turn quickly if I do. Thanks for the input! – user1130005 Jan 17 '12 at 11:11