Some background first:
I am working on some legacy code that implements UI interfaces. The code is structured in a way that it has a base class (actually it's a struct) WinBase which is then derived to all sorts of graphical objects.
WinBase:
- Button
- DialogWin
- (etc...)
- EditWin
WinBase has a member WinBase **children that is used to keep tabs on all of the children of each object. These children are created and destroyed during runtime in the standard new[]/delete[] fashion.
All methods/functions of these objects assume that they are receiving a pointer to a WinBase object, and dynamic_cast<> is used to ensure/validate that the appropriate pointers are being used.
A later change to the code added two more classes/structs (ListBox and TextBox), that are derived from EditWin which in turn is derived from WinBase.
So... I have pointers to WinBase that being casted to ListBox and TextBox. As I said, dynamic_cast<> is used throughout the code, but I am not sure how safe this is when a function like this constructor is called.
TextBox(WinBase *pw,(...));
How safe is it to cast directly from WinBase to ListBox and vice versa (for instance)?
First of all, why would you want to cast a WinBase to a ListBox when a ListBox is given to a method expecting a WinBase? If you need a cast there, you should re-think the design, as methods expecting the WinBase should operate only on WinBase's interface.
If, and only if, ListBox is derived from WinBase (either directly or indirectly), you can always cast from a ListBox* to a WinBase* (or reference), because a ListBox IS A WinBase.
Casting the other way around is NOT safe, because you will never know if the WinBase* you got is actually a ListBox* or something else and that calls for trouble. You can of course use dynamic_cast<> to test if it really is a ListBox*, but any dynamic cast calls for a review of your design.
Especially that kind of down-cast calls for trouble in a constructor, because when you are not getting what you wanted, what is your code supposed to do? Throwing exceptions, as the only way out is not such a good idea and at its best avoided at all (unless you know what you are doing).
So, you can try to use boost::polymorphic_cast or boost::polymorphic_downcast http://www.boost.org/doc/libs/1_50_0/libs/conversion/cast.htm it`s throw exception if dynamic_cast returns 0.
Related
Okay, so my situation is really complex to a relativity new person to C++ like me. I'm making a game (AGK library) and I have a framework class that is the base class for all of the game's objects to have standard functions like frameEvent and such that are to be overwritten by the child object.
That's all fine and dandy, and I've gotten about 70% through development, but I ran across one vital problem.
To make life easier while processing the game, each object that is a part of the game is just a pointer in a vector of type Framework*. Framework being the base class. I was told that making it a pointer allows me to have child objects of different types as long as they're a pointer as well. So far it's worked out.
Every frame, the global object runs through the vector of all the objects and runs their
frameEvent
frameEndEvent -- Can't be overriden
drawEvent
They're really just functions. So in the enemy's bullet class, I need to check if it collides with oPlayer, so I have a functions in the global class (The global class is passed to the objects in their frame event so they can communicate with other objects.) that grabs a given object.
It searches through all of the objects to find the parameter object -- so if I pass new oPlayer, it will return the real oPlayer pointer in the game.
When the bullet collides with the player, it needs to lower the player's health and then destroy itself. So at the create function for the bullet, it creates a dummy player then locates the real one using the global class function. The code is
//Find the player
oPlayer* tempPlayer = new oPlayer;
playerChecker = ObjGlobal->classToObject(tempPlayer);
tempPlayer->objectDestroy();
That code works, but it needs playerChecker to be type Framework* because that's what classToObject returns. But when I later use that pointer, I can't access the player's members even though that's the player's pointer.
playerChecker->hitPoints--;
hitPoints is exclusive to oPlayer. I think it's called object splicing or slicing, but I thought that's what using pointers fixed.
So I tried to make playerChecker type oPlayer*, but it says that Framework* can't be converted to it. So I have no idea what to do.
Any help is greatly appreciated.
Your Framework* from classToObject can be downcast to a oPlayer* using a dynamic_cast, like so:
oPlayer* playerChecker = dynamic_cast<oPlayer*>(ObjGlobal->classToObject(tempPlayer));
if (oPlayer) {
// cast succeeded, do stuff with the pointer
}
dynamic_cast is a C++ type cast operator just like the C-style cast, with some special properties. It is specifically designed to convert between pointers or references to polymorphic objects (like your oPlayer, which can be treated as both a Framework and an oPlayer). It also adds a run-time check which verifies that the object you're trying to downcast is indeed an instance of the class you're trying to cast to. If it isn't, it will return a null pointer, or in the case of references, throw an exception.
Your code will also work with a C-style cast or a static_cast (which is much like a C-style cast with compile-type type checking).
static_cast<oPlayer*>(ObjGlobal->classToObject(tempPlayer)) // static_cast
(oPlayer*)ObjGlobal->classToObject(tempPlayer) // C-style cast
These have less overhead because of the lack of a run-time check, but that also means that they are unsafe unless you can guarantee that the pointer you're casting points to an object of the correct type. Also, since dynamic_cast has a very specific use, it makes it clear what your intent is.
What's the error you're getting? Please post this, as we can't offer much help otherwise.
If I had to guess, you forgot to add public: to your class FrameWork. This, or you don't have setters/getters in your class.
I have a class MyAction which derives from the QWidgetAction which derives from the QAction.
When I call QWidget::addActions(QList<QAction*> actions), I have exception on trying to get d_ptr and use it (inside QWidget, not by myself) from action in list:
QActionPrivate *apriv = action->d_func();
apriv->widgets.append(this);
Code above is taken from QWidget source file. By the way, my action is placed in actions list as cast of this pointer which of type MyAction:
actions->push_back(this);
I think that the reason of exception in that that I trying to push into QList my class MyAction, casting const this pointer to QAction*.
If d-pointer pattern is used properly then it never can be null.
D-pointer have to point to valid memory block which will live as long as object lives.
Only exception for this role are classes implementing copy on write which provide null state (for example QString), but this never applies to QObjects.
Your problem must be result of some dangling pointer or other memory issue. Or incorrect type casting. In such cases call stack doesn't have to point to source of problem, problem can be almost anywhere.
I recommend to run your program with valgrind or other memory checking tool. Or some static analysis tool.
You should never use d_func() from client code. The whole point of the pimpl idiom is to stay away from the implementation details and that the library can freely change implementation details like data representation, internal methods and so on.
That is, d_func() along with d_ptr is meant for internal usage. If you need to access it for some reason, that means you seem to violate the design principle of the library, or you are trying to access something that should be exposed to the API, but was not yet needed.
Based on your exact use case - which we do not know, I would suggest to consider these alternatives.
The problem was in that I created MyAction variable on the stack, so, actually, QObject wasn't alive when I'm trying to pass it to QWidget function. That's why I couldn't get d-pointer different from NULL. I couldn't knew that object was actually dead, all strings and variables inside my action was valid.
Say in a game, we have Entities that communicate with each other. Say a player collides with an Item and now, that item should be placed in his std::vector<Item*>
When the player receives the collision message, he receives the item as an Entity*. Would it then be appropriate for the player to cast it as an item, and if the cast succeeds, to push the item into the inventory?
Even if the game sent him a HIT_ITEM message, he would still need to cast it to push it in.
Thanks
dynamic_cast helps you check the validity while performing downcasting.
It returns a NULL or throws an exception(std::bad_cast for References)if the pointer or the reference cannot be safely downcasted.
It is unclear to say unless you show us the class structures.
If you can satisfactorily answer these questions for yourself, then yes.
Why does the player receive the collision message with an Entity* rather than an Item*?
at the point of the potential cast, are you SURE it'll be of dynamic type item? What if it isn't ?
Is there any way you could relatively painlessly redesign your code to avoid the cast?
Anyway, don't be dogmatic. If in the current circumstances a downcast is more convenient than other things, do it. IMHO
The main question you should ask yourself is- could I just make this a virtual function on Entity? In this case, I would probably say "no", because it doesn't make sense for non-Items to know or care about what you're gonna do with an Item. So dynamic_cast probably is the right solution- you can safely handle the case of null coming back and it keeps the other derived classes from having to know anything about Item.
How about adding a type member together with a GetType() function to the base class? This is how I usually solve those "casting" problems.
In addition don't forget to turn on RTTI if you are going to use dynamic_cast (please ignore it this was obvious).
I have a pointer to a QScriptEngine that I'm passing through the overloaded class constructor of class Evaluator and assigns it to QScriptEngine *engine_ (class Property subclasses Evaluator, and calls this constructor of Evaluator, passing it an already allocated QScriptEngine). The constructor with no arguments creates the new QScriptEngine pointer (class Generic subclasses Evaluator in this way). In the destructor I test if engine_ is not NULL, delete the pointer, then assign it NULL. Should the pointer (engine_) in the derived Property now also be NULL? Something tells me this is not the case. If not, how do you deal with this situation? I need the QScriptEngine to be the same instance throughout. QScriptEngine's = operator is private, or I would be avoiding the pointer all together.
I saw some info on shared pointers (boost::shared_ptr and std:tr1::shared_ptr) in another SO question. I'm already using boost for the regex library, so boost is not out of the question if that's the best way to deal with this. Hopefully there's a non-boost way, for general C++ knowledge and future projects.
You can solve this by giving one of the classes (class A) lifetime control of that pointer, along with a 'getter' method. The other class (class B) would always call A's getter whenever it needed the pointer. That way, A remains in control of the pointer at all times. Downside is the getter function (it will probably inline, but it's still a second indirection). Also, B is going to have to check that pointer for NULL on pretty much every use.
Your other choice is to wrap the pointer in something like boost::shared_ptr which takes care of the problem (if used properly) by holding the underlying pointer, and only deleting it when all objects that share that pointer are deleted. You could write this yourself, but since you already have boost in play, I'd just use their implementation.
A third choice is to re-factor the whole thing so that you don't need a shared pointer. I'd personally never design a C++ program that needed shared pointers, just because it's a spot where memory management bugs could easily creep in over the years, but that's just me.
i need to convert pointers to long (SendMessage())
and i want to safely check if the variable is correct on the otherside. So i was thinking of doing dynamic_cast but that wont work on classes that are not virtual. Then i thought of doing typeid but that will work until i pass a derived var as its base.
Is there any way to check if the pointer is what i am expecting during runtime?
Is there a way i can use typeid to see if a pointer is a type derived from a particular base?
Your reference to SendMessage() makes i sounds like MS Windows is your platform and then the Rules for Using Pointers (Windows) is recommended reading. It details the PtrToLong and PtrToUlong functions and other things Microsoft provide for you in situations like this.
If all you have is a long, then there's not really much you can do. There is no general way to determine whether an arbitrary number represents a valid memory address. And even if you know it's a valid memory address, there is no way to determine the type of the thing the pointer points to. If you can't be sure of the real type of the thing before its address was cast to long, then you can't be sure that it's going to be safe to cast the long to whatever type you plan on casting it to.
You'll just have to trust that the sender of the message has sent you a valid value. The best you can do is to take some precautions to reduce the consequences to your own program when it receives a bogus value.
You cannot use typeid. It will result in an Access Violation if you get garbage instead of a valid pointer, so your check is nonsensical.
What you should do, is wrap your SendMessage and the code which processes the message into a single type-safe interface. This way you will be unable to pass unexpected things to SendMessage, and will not need any checks on receiving side.
C++ type system works at compile time. Once you cast a pointer to a long, you loose all type information. A long is just so much bits in memory; there is no way you can identify that it was pointing to an object.
PTLib ( http://sourceforge.net/projects/opalvoip/ ) uses a PCLASSINFO macro to define relations between classes. This provides functions like IsDescendant and GetClass.
You could probably implement something similar.
dynamic_cast works by checking the signature of the virtual method table. If you have no virtual methods, you have no VMT, so as you say dynamic_cast won't work. However, if you have no VMT, you have absolutely NO knowledge about the object being pointed to.
Your best bet is to require that pointers are to classes with at least one virtual method, even if it's a dummy. Dynamic cast will work then.
I don't understand yet what your question is about.
If it is whether or not you can be sure that casting to a long and back will yield the same value, view Safely checking the type of a variable
Given the "Rules for using Pointers" MS-Site the other Answerer linked to, the right type to cast to is UINT_PTR. So you do UINT_PTR v = reinterpret_cast<UINT_PTR>(ptr); to cast to a integral type, and do the reverse to cast it back to the pointer again. The C++ Standard guarantees that the original value is restored. (see the link i gave above for my explanation of that). That Microsoft site by the way also says that WPARAM and LPARAM change their size depending on the platform. So you could just use that variable v and SendMessage it.
If it is how you can check on the other side whether or not the pointer (converted to some pointer type) points to some object, the answer is you can't. Since you are apparently not sure which pointer type was used to send it, you cannot check on the receiving side what the dynamic type the pointer points to is. If you know the type the pointer had on the sender side, your check would be not required in the first place.
In Windows, MFC provides a method to check if a given pointer is pointing to a valid memory location (this is done by trapping segfault). I do not remember the function name, but it's there. Still, it does not ensure that the contents of the memory pointed to are valid. It may still have invalid VMT and crash your code. Of course, you can trap the segfault yourself (see MS Knowledge Base)
As for checking if something belongs to a type, you must have a base class to start with. If you make the destructor of base class "virtual", all derived classes will have VMTs.
If you must avoid VMT at all costs, you have to have some sort of descriminator that tells you what you're dealing with, such as event type in MS Windows events.