Jump to content
  • Advertisement
Sign in to follow this  
grelle

Pointer trouble

This topic is 4546 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Does anyone know a way around this error without a manual cast? (Some kind of template construct perhaps?)
class Base {};
class Inherited : public Base {};

void Func(Base **pBase);

Inherited *pInherited;
Func(&pInherited); // <-- error C2664
'Func' : cannot convert parameter 1 from 'Inherited **' to 'Base **' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

Share this post


Link to post
Share on other sites
Advertisement
You cannot, it's unsafe; as always, you can do it manually, but C++ finds it too dangerous.

This (rather dashing) page explains why: http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.2

In short, if it were possible you could end up with one derived class' pointer-to-pointer point to another derived class' pointer-to-pointer, causing dangerous behaviour.

I'm not sure how I'd go about going around it, you can always c-style cast, even though that's dangerous, if you know what you're doing (along with the others using your code) it's not a crime against humanity, just a crime against style.

Share this post


Link to post
Share on other sites
yeah, but in this case I really need the address, and the Base class is an interface that doesn't inherit from anything else.
But that doesn't matter because I only use the adress to store a new pointer during deserialization and thus the whole operation is inherently unsafe. =)

The reason I want to do it automatic is because the code gets really ugly with all those manual casts everywhere. I guess I could do it with macros

Share this post


Link to post
Share on other sites
If you're sure you won't be doing anything 'wrong' in there, you could maybe use a templated proxy function that takes care of the casting (and possibly template type checking to make sure what you're casting from is inherited off Base)

Share this post


Link to post
Share on other sites
Quote:
Original post by grelle
yeah, but in this case I really need the address


Are you sure? This smells a lot like a situation where you should be passing by reference instead - and typing the parameter in the caller as a Base* even though it happens to point to a Derived object. Assuming the reason for the double-pointer (strongly suggested here by context) is to modify what is being pointed at in the caller, keep in mind that the current setup might also change the exact subtype.

Share this post


Link to post
Share on other sites
Quote:
Assuming the reason for the double-pointer (strongly suggested here by context) is to modify what is being pointed at in the caller, keep in mind that the current setup might also change the exact subtype.

I will in effect decide the subtype when the object is read from a stream. Assuming the stream is not "hacked" it will contain the correct subtype.

However, as you suggested, I could use a const reference to the pointer instead. That would get rid of all manual casts, but I would have to do a const_cast on the reference to modify its value.

Something like this:
Func(Base *const &Ptr) { const_cast<Base *&>(Ptr) = newptr; }

Inherited *pInherited;
Func(pInherited); // <-- No error

Share this post


Link to post
Share on other sites
If I understand you correctly, you'll be using 'Func' to deserialize objects.. surely then, you don't know the type of the object before it's been deserialized, and as such how can you be passing in a pointer to a pointer to a derived type?

Even if you do know the type (for whatever reason), I think you should let the deserialization function deserialize the object, and pass it back as the base type object. At which point you could do a dynamic cast to assign to your derived type pointer in a safe manner.

Share this post


Link to post
Share on other sites
Quote:
Original post by c2_0
If I understand you correctly, you'll be using 'Func' to deserialize objects.. surely then, you don't know the type of the object before it's been deserialized, and as such how can you be passing in a pointer to a pointer to a derived type?

Even if you do know the type (for whatever reason), I think you should let the deserialization function deserialize the object, and pass it back as the base type object. At which point you could do a dynamic cast to assign to your derived type pointer in a safe manner.


Quoted for emphasis.

Also, don't pass a const reference and then const_cast the constness away, when the whole point of the function is to assign to that parameter. Just pass a non-const reference.

Share this post


Link to post
Share on other sites
[Zahlman]
Quote:
Just pass a non-const reference.
It is as ilegal to pass a non-const reference to Base* as it is to pass a Base** if the type is derived from Base. And with that solution I get the original problem with manual casts.

[c2_0]
Quote:
I think you should let the deserialization function deserialize the object, and pass it back as the base type object. At which point you could do a dynamic cast to assign to your derived type pointer in a safe manner.

First of all, I have to be able to assume that the stream is not corrupt. If the stream is corrupt it could generate any kind of bogus data, and dynamic_cast will not solve that. Corrupt streams needs to be handled before the deserialization begins, with other types of verifications.

And I cannot return the newly created object immediatly because the operation is asynchronous. I also need/want all addresses for verification/debug purposes. And it works fine for 'standard' types, as I only pass a reference to them. The only problem I have is with derived pointer types.

I know that const_cast is kind of ugly but that is the easiest solution to my original problem I've found so far...
[edit]actually, I did not find it. Zahlman pointed it out to me, thanks for that =)[/edit]

[c2_0] You mentioned a 'templated proxy function' earlier. I have tried to come up with something, but failed. Do you have any suggestions on this?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!