calling functions using "->" - c++

I'm currently learning about virtual functions, and in this particular lesson it creates an array of object pointers firstArray[5], and calls functions from these objects. Until now, whenever I wanted to call a function func() from an object foo, I would write foo.func(). Now that I'm using virtual functions and this array, the book has switched to this method: firstArray[0]->func(). The book doesn't do a great job at justifying this switch, could someone please explain? I see that when I try to use firstArray[0].func(), I get this....
error: request for member 'func' in 'firstArray[0]', which is of non-class type 'sampleClass*'.
Is it simply because I'm trying to call a function from a pointer, not an actual object? I've been learning C++ for several months now, and for whatever reason pointers still trip me up sometimes. Any clarification would help.
EDIT:
I think the part that got me mixed up is this: I can create a pointer to a base object class with base *ptr;. Then, I can set that pointer by creating a new object from a derived class by saying ptr = new derived;. This is where I get confused. If I were to create an int* ptr;, and I wanted it to point to a integer I create, I couldn't say ptr = int j. If ptr is really just an address, why do these two examples work differently? I guess I don't understand the "new" mechanic very well either.

That doesn't have anything to do with virtual functions. If you have a pointer you need operator-> to deference and access the object it's pointing to....
You could still use the operator. (dot) to access the members/functions if you dereference first:
(*foo).func()
A pointer to an object just holds the address where the object is held in memory.
So if you have a variable which is a pointer to some type, it actually holds a number.
If you want to use the object, you need to call the object it is pointing to, which is as I said by using either operator* or operator. (dot).

Related

using pointers in managed C++ in non-managed library methods

I have a managed C++ wrapper class for a non-managed C library. I came across an issue where it seems that the pointer I am sending from my managed C++ class is not pointing to the same memory location which is used by the non-managed C code library method.
MyNonManagedType* dataPointer;
getDataFromNonmanagedCLibrary(dataPointer);
// this gives me junk data, where field should be a char array
String^ myFieldValue = gcnew String(dataPointer->field);
Is it possible that the dataPointer is not pointing to the same address used by the C library? Or maybe there is some kind of marshal method I need to use for this, or other pitfalls I may be missing?
If the pointer is not managed, given the code you have shown, there is no way for a C function to do anything with the uninitialized pointer except either:
Check it for NULL, and if so, do nothing with it, or
Use the address passed, and disaster happens.
You are passing the pointer by value, and passing by value means that the function will be using a local copy of the parameter that is passed, thus you see no changes when the function returns. The function cannot set the pointer and have those changes reflect back to the caller the way it stands now.
Since we're talking about a C interface, you should change the C interface to this:
void getDataFromNonmanagedCLibrary(MyNonManagedType**);
A pointer to the pointer is passed. Since we want to change the value passed to the function and have it reflect back to the caller, a pointer to the value is passed. Since the value just happens to be a pointer, we pass a pointer to the pointer.
Then you rewrite getDataFromNonmanagedCLibrary to initialize the pointer by dereferencing it:
void getDataFromNonmanagedCLibrary(MyNonManagedType** ptr)
{
*ptr = <the_address_you_expected_on_return>;
}
Then on the client side:
MyNonManagedType* dataPointer;
getDataFromNonmanagedCLibrary(&dataPointer);
Note that the address of the pointer is passed, no different than if you wanted to have a function change a non-pointer variable by passing the variable's address.

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

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.

How to change an instance of a class into an instance of a subclass

Basically what I am trying to do is set an instance of class 'MovingHero' into a 'ShootingHero', which is a subclass of 'MovingHero'.
As I have it now, the MovingHero class has a function called levelUp() that looks like this:
MovingHero levelUp()
{
ShootingHero theHero();
return theHero;
}
and in my main function I have:
if(hero1.getScore() == 5)
hero1 = hero1.levelUp();
I'm not getting any errors, but after the if statement executes, hero1 is still a MovingHero rather than a ShootingHero.
I think this has something to do with operator overloading but I'm just not sure. Any help would be appreciated. Thanks!
Operator overloading?! No, it has nothing to do with that.
When you return from that function, you slice your ShootingHero object† into a new MovingHero. In order to take advantage of dynamic polymorphism, you need to employ indirection. That means pointers and/or references.
You can't use object copying and keep the original most-derived type: your assumption that you have a MovingHero to work with is incorrect. Please read the chapter in your C++ book about polymorphism.
† Actually, you don't have a ShootingHero object, because you wrote ShootingHero theHero(); which is a function declaration. The code you showed us will not compile; you probably meant ShootingHero theHero;.
Polymorphism only works with pointers (and technically references, although this isn't as common). MovingHero and ShootingHero are two different types; there is no way to successfully assign objects of one type to another.
MovingHero* and ShootingHero* however are both essentially the same type (a pointer) differing only in the type of data the point to (which has no effect on the actual pointer (it just provides the compiler with information regarding what is considered "legal")), so you can successfully assign pointers to ShootingHero objects to pointers to MovingHero objects.
Indeed, you can always assign pointers of any type to pointers of any other type using a cast, although this will more often than not lead to garbage values when you dereference the pointers. However, polymorphism guantees that the conversion will be valid, so there is no need for a cast.
Using polymorphism, your function could be written:
MovingHero* levelUp()
{
ShootingHero* theHero = new ShootingHero();
return theHero;
}
Note that you must manually delete this pointer at some point, as it is dynamically allocated.

C++ Pointer Assignment (Point to a Vector)

This is my first post in any forum so please bear with me.
I am writing a C++ program that utilizes a custom class 'Book' with member variables such as title, author and other variables that are stored in strings. Amongst these member variables is a vector for storing objects of type Review (which is another custom class). Now in my driver file (where the main() is located) needs to access that vector (the Reviews vector in each Book object) and make changes to it as well. I realized that I need to utilize a pointer of type vector
(eg.
vector pointerName
). So I added another member variable to the Books class which is a pointer. The problem I am facing is to point that pointer to the vector. Where can I make this assignment? I tried de-referencing it and pointing it to the vector in the default constructor for the object, but that causes my program to crash at run time without throwing an exception. The line I put in the constructor is
*pointer = vector_of_reviews;
I am new to this forum and still learning how to go about posting here so please bear with me if I have made a mistake in my post or if I was unclear or insufficient with my information. Please let me know if I need to post or say anything more to make my stance clear.
Thank You.
To assign a pointer to 'point to' an instance of an object use pointer = &vector_of_reviews.
The & operator gets the address of something, and it's this that you want to assign to the pointer.
*pointer = vector_of_reviews dereferences the pointer (obtains the actual object 'pointed to'). This would more than likely crash if the pointer is yet to be initialised. If the pointer was valid this would perform a value assignment, ie. invoke the vector class's assignment operator.

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.