I can't access members of a child class through functions, how do I? - c++

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.

Related

Multiple object type container or dynamic casting for a game project?

I have a very specific... well, lets not call it a problem, lets rather call it a deadlock. I'm writing a simple 2d game using allegro5 along with c++, and have a specific problem I'd like to overcome.
Main problem:
Currently, for game loop i'm using a list container, which holds all of my objects (of type GameObject) inside, and then im iterating on it to do things like updating the objects positions, rendering and animatating sprites.
From the class GameObject (which hold generic information used for updating, rendering and memory handling methods) inherits a Creature class, which should handle things like attacking methods.
The problem that comes up is that when iterating my main list of GameObjects (which would include Creatures as well) i cannot directly use the methods of my Creatures class. Of course I understand why I cannot do that (Encapsulation).
So far I've come to few possible solutions (which, in my humble opinion are not perfect), but I would like to ask for help in helping to find easy to implement and efficient solution:
- Using a container that could hold multiple object types.
- Using dynamic_cast at some point, to cast a creature GameObjects to Creature class to temporary use Creature methods and variables (is that even possibile?)
- Setting up a second container for handling the Creature methods and variables (I would like avoid that, as then I would need a single object to be in two containers at once - when adding new types of classes 'buildings', 'obstacles' or 'arrows' thier number will grow!)
I'm a very beginner programmer, and as I understand creating a game could be kind of overkill for my level of skill, im determined to push this game forward with any means nessesary. (Especially since I've learned a lot so far)
I hope I've explained a problem in detail - i'm not posing any code here, as its more of a theoretical problem then practical one, im just iterating a GameObject list after all.
With regards,
As you've found out, containers can only hold one type of object at a time.
If that object type is a base class pointer, it can point to any object derived from the base class. However, you need to first cast the pointer to the appropriate type before you can use it's specific abilities.
You answered your own question when you brought up dynamic_cast.
You can use dynamic_cast on the base pointer stored in your container to determine if the object is actually of a different type derived from your base class.
See the section on dynamic_cast here :
http://www.cplusplus.com/doc/tutorial/typecasting/
Example
Derived* d = dynamic_cast<Derived*>(ptr_base_class);
if (d) {/* We now know that ptr_base_class holds an object of type Derived */}
else {
/// This object is not a Derived class type
}
However, if you had to iterate over your entire base class pointer list using dynamic_cast to determine if an object is of a specified type, it would be wasteful.
Here's where you answered your own question again. Keep a separate list of all Creature*s so you don't have to cast them. Yes, you will be using a /little/ more memory, but not much. Being able to iterate over the Creature list without iterating the entity list improves your performance. To make things easier, make your own container that has a list of each type of object as well as a main list of all objects. If you don't care about their derived class, iterate the main list. If you care about what class they are, iterate their specific list.

Is it alright to return a reference to a non-pointer member variable as a pointer?

I recently came across some C++ code that looked like this:
class SomeObject
{
private:
// NOT a pointer
BigObject foobar;
public:
BigObject * getFoobar() const
{
return &foobar;
}
};
I asked the programmer why he didn't just make foobar a pointer, and he said that this way he didn't have to worry about allocating/deallocating memory. I asked if he considered using some smart pointer, he said this worked just as well.
Is this bad practice? It seems very hackish.
That's perfectly reasonable, and not "hackish" in any way; although it might be considered better to return a reference to indicate that the object definitely exists. A pointer might be null, and might lead some to think that they should delete it after use.
The object has to exist somewhere, and existing as a member of an object is usually as good as existing anywhere else. Adding an extra level of indirection by dynamically allocating it separately from the object that owns it makes the code less efficient, and adds the burden of making sure it's correctly deallocated.
Of course, the member function can't be const if it returns a non-const reference or pointer to a member. That's another advantage of making it a member: a const qualifier on SomeObject applies to its members too, but doesn't apply to any objects it merely has a pointer to.
The only danger is that the object might be destroyed while someone still has a pointer or reference to it; but that danger is still present however you manage it. Smart pointers can help here, if the object lifetimes are too complex to manage otherwise.
You are returning a pointer to a member variable not a reference. This is bad design.
Your class manages the lifetime of foobar object and by returning a pointer to its members you enable the consumers of your class to keep using the pointer beyond the lifetime of SomeObject object. And also it enables the users to change the state of SomeObject object as they wish.
Instead you should refactor your class to include the operations that would be done on the foobar in SomeObject class as methods.
ps. Consider naming your classes properly. When you define it is a class. When you instantiate, then you have an object of that class.
It's generally considered less than ideal to return pointers to internal data at all; it prevents the class from managing access to its own data. But if you want to do that anyway I see no great problem here; it simplifies the management of memory.
Is this bad practice? It seems very hackish.
It is. If the class goes out of scope before the pointer does, the member variable will no longer exist, yet a pointer to it still exists. Any attempt to dereference that pointer post class destruction will result in undefined behaviour - this could result in a crash, or it could result in hard to find bugs where arbitrary memory is read and treated as a BigObject.
if he considered using some smart pointer
Using smart pointers, specifically std::shared_ptr<T> or the boost version, would technically work here and avoid the potential crash (if you allocate via the shared pointer constructor) - however, it also confuses who owns that pointer - the class, or the caller? Furthermore, I'm not sure you can just add a pointer to an object to a smart pointer.
Both of these two points deal with the technical issue of getting a pointer out of a class, but the real question should be "why?" as in "why are you returning a pointer from a class?" There are cases where this is the only way, but more often than not you don't need to return a pointer. For example, suppose that variable needs to be passed to a C API which takes a pointer to that type. In this case, you would probably be better encapsulating that C call in the class.
As long as the caller knows that the pointer returned from getFoobar() becomes invalid when the SomeObject object destructs, it's fine. Such provisos and caveats are common in older C++ programs and frameworks.
Even current libraries have to do this for historical reasons. e.g. std::string::c_str, which returns a pointer to an internal buffer in the string, which becomes unusable when the string destructs.
Of course, that is difficult to ensure in a large or complex program. In modern C++ the preferred approach is to give everything simple "value semantics" as far as possible, so that every object's life time is controlled by the code that uses it in a trivial way. So there are no naked pointers, no explicit new or delete calls scattered around your code, etc., and so no need to require programmers to manually ensure they are following the rules.
(And then you can resort to smart pointers in cases where you are totally unable to avoid shared responsibility for object lifetimes.)
Two unrelated issues here:
1) How would you like your instance of SomeObject to manage the instance of BigObject that it needs? If each instance of SomeObject needs its own BigObject, then a BigObject data member is totally reasonable. There are situations where you'd want to do something different, but unless that situation arises stick with the simple solution.
2) Do you want to give users of SomeObject direct access to its BigObject? By default the answer here would be "no", on the basis of good encapsulation. But if you do want to, then that doesn't change the assessment of (1). Also if you do want to, you don't necessarily need to do so via a pointer -- it could be via a reference or even a public data member.
A third possible issue might arise that does change the assessment of (1):
3) Do you want to give users of SomeObject direct access to an instance of BigObject that they continue using beyond the lifetime of the instance of SomeObject that they got it from? If so then of course a data member is no good. The proper solution might be shared_ptr, or for SomeObject::getFooBar to be a factory that returns a different BigObject each time it's called.
In summary:
Other than the fact it doesn't compile (getFooBar() needs to return const BigObject*), there is no reason so far to suppose that this code is wrong. Other issues could arise that make it wrong.
It might be better style to return const & rather than const *. Which you return has no bearing on whether foobar should be a BigObject data member.
There is certainly no "just" about making foobar a pointer or a smart pointer -- either one would necessitate extra code to create an instance of BigObject to point to.

C++ - Allocating on heap than using new object as reference to maintain interface

I have a case in my application where I need to create a new object dynamically based on what type info I get back from an external source. Basically, I have class A that handles this task. The class will either create class B, C, or D, etc. (say B is the base and C and D are derived types). Then I want to pass this object to an existing interface that is full of methods that expect a reference parameter of type B. Eventually this dynamically allocated object is stored in a boost::shared_ptr member object of another class (I use the reset() method on the shared_ptr). So at that point the memory is being managed by someone.
Basically it seems like this is bad design to me (that I'm passing this dynamically allocated object all over the place, dereferencing it at one point and then getting the pointer to it again later). On the other hand, I don't want to change several methods of an interface to take a pointer rather than a reference. I would like to leave that interface alone and dereference the pointer when I'm passing the object on to the interface for further processing. I read somewhere that when you have a method that takes a reference parameter, you're saying "I'm not concerned about memory management here" and "this object will be initialized - i.e. can't be NULL". The object was originally created on the heap though and will eventually be "owned" by another class that will manage its memory. Is still OK to have these interface methods take reference parameters in this case?
I think that the primary goal of design in terms of object usage and lifetime should be that the ownership of the object is clear and well-understood at all times. The creation and deletion is ideally handled in only one place, or is clearly signposted when you are creating and handing-off somewhere else - again, that should be done only in one place.
My preference would be that until the object is owned outright by some piece of code, then pointers should be used. Once it is owned, then the owner can pass it on as a reference.
With pointers, it's okay to interpret as "here's an object - does anyone want it?"
With references, you're saying "here's MY object - you can use it"
But if that forces you to makes the rest of your code ugly and confusing, then maintaining that ideal is not worth the price you pay. If you can at least make the creation and hand-off look clean, then you can hide the quirky stuff in some other (well-documented) part of the code...
B * myInst = A::BFactory( current_state_of_universe );
bool bSubmitted = SubmitForMagic( myInst );
if( !bSubmitted ) delete myInst;

multiple levels of inheritance and dynamic_cast

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.

Deleting a Shared Pointer

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.