Regarding: Child Class in a Array C++ - c++

Regarding: Child Class in a Array C++
Hi guys, sorry as i am stuck on some work.
Basically this is what happen
I have a parent class call vehicle and it got 2 child class call
Car and Motorcycle
Parent class have the following value:
string Name: value either Car or MotorCycle
wheels : 4 or 2 (depends is car or motorcycle)
Notes On Wheel:
wheel[0] : Fine condition
wheel[1] : need some repair
wheel[2] : Fine condition
wheel[3] : Fine condition
I wonder how do i record this all in VehicleTwoD Array
Car / Motorcycle is a child class of Vehicle, what do you guys suggest. I try to create an object of VehicleTwoD vehtwod[100];
then i do a for loop to prompt. but how do i record the object car / motorcycle into my VehicleTwoD array and how do i record the string array inside too. so every VehicelTwoD array element contains the information
Name ( Motorcycle or Car)
Wheel ( depend on name - 2 or 4)
String array - notes size depend on what is choosen
How do i record all in 1 array.
Thank you very much , i know this is polymorphic and i know this is OOP and i know i need study more. but i really stuck on this part on creating such array that can hold other array.
THANKS!

Simplifying solution by not addressing irrelevant dimensionality of the storage array.
Create an array of Vehicle pointers, and store those:
vector<unique_ptr<Vehicle>> vehicles_;
vehicles_.push_back(new Car(...));
vehicles_.push_back(new Motocycle(...));
Since we're using unique_ptr here instead of a raw pointer, there's no need to explicitly delete.
By making the class polymorphic you can declare functions on the base class and implement class-spefici functionality by providing definitions in the derived classes. This makes it possible to call methods through a pointer to the base class without having to cast to the derived type.
If you need to call methods that exist only on a derived class, then you will need to cast the pointer. This should be done using dynamic_cast, and requires that your class is polymorphic.
EDIT:
Your comments suggest that you don't know how to use a vector and would prefer to use a raw array. That's fine too. Here's a simplified example that uses a C-style array of raw pointers. Note that by using neither vector nor a smart pointer like unique_ptr you make your code more brittle and prone to errors, and you often have to use a Magic Number for the array size (which is gross).
Vehicle* vehicles_[100];
vehicles_[0] = new Car(...);
vehicles_[1] = new Motorcycle(...);

Related

Access violation when attempting to access object member variables in an array

My program/assignment, a "zoo simulation" involves dynamic arrays [can't use vectors] of different species animal objects that inherit from the Animal base class. But my problem seems to be very simple (I hope):
I've been using the construction
Animal **arr = new Animal*[10];
but reading arr[0]->getAge() causes an access violation.
I'm trying to simultaneously understand pointers but also maybe get the code right pre-complete understanding because of a deadline.
I've tried
*arr = new Animal[10]
but run into problems when I want to add/change objects in the array, or delete an array. Perhaps the
** new *
only works with certain variable types and not class objects. I can set up an array with the
*arr = new Animal[10];
formation but then when I try to set something like
arr[05] = to a new Tiger object,
nothing changes, so I'm hitting a wall.
Basically I need to initialize an array of Animal objects, and then add inherited class objects to the array. Thanks for any insight and apologies for my newbishness.
In
Animal **arr = new Animal*[10];
Animal **arr declares a pointer to a pointer. new Animal*[10] allocates 10 pointers to Animals. These 10 pointers are uninitialzed and don't point anywhere safe to use.
arr[0]->getAge();
gets the firs of these 10 pointers and attempts to use what it points at. Since it doesn't point at a valid Animal anything can happen. In this case it appears that the program crashes. This is one of the better outcomes because it makes the mistake instantly noticeable.
Now assuming Tiger derives from Animal
class Tiger: public Animal
{
// definition of Tiger
}
then you can later
arr[0] = new Tiger;
to point the first of the 10 pointers at a valid instance of Tiger and then you can
arr[0]->getAge();
When you are done, don't forget to delete all of the Animals and to delete[] arr.
Sidenote:
Don't write code like this. It is extremely fault-prone. Instead take advantage of Standard Library containers like std::vector and prefer smart pointers like std::unique_ptr to manage the program's dynamic memory. Example:
std::vector<std::unique_ptr<Animal>> arr;
Makes a resizable array of Animals that will all automatically be deleted when arr is no longer needed and goes out of scope.
Adding a Tiger would look like
arr.push_back(std::make_unique<Tiger>());
This LOOKS more cumbersome, but it saves you from having to find the exact places in the code where you must delete your resources and make absolutely certain that they are deleted.
You've allocated an array of pointers but you have not actually allocated any objects for those pointers to point at. So arr[0]->... is undefined behavior.

Copy-constructor for array of abstract pointers

I'm making a copy-constructor in a class called Registry, which handles an array of pointers of the abstract class Competitor, while Amateur and Professional inherit from Competitor.
How would I go about transferring these to the array of the new Registry-object from the Registry-object I passed in to copy from?
Usually when I'm dealing with a concrete class I would make a for-loop and then do something like:
for(int i=0; i<this->size; i++)
this->arrOfComp[i] = new Competitor(*original.arrOfComp[i]);
Where original is a parameter of type Competitor.
But I can't allocate Competitor obviously now that it is abstract. And I don't know what type the next object in the array is, so I can't just change it to ... new Amateur(...) or ... new Professional(...), they're not all the same, it's mixed; some are Amateurs, some are Professionals.
Is there some elegant way of making it transfer every object regardless of class so I don't have to write two if-statements and use typeid, dereferencing etc.?
And I know vectors might be the first thing that may come to your mind, but this is an assignment and I don't have a choice.
I checked this one:
Copy constructor for abstract class
But it was about Java, I don't know how to make that for C++.

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.

I have a vector of Base and Derived Class Objects, but I can't access data members inherited by derived objects that are stored in the vector

Bear with me, I'm relatively new at C++.
Here is my project. I want to essentially create a simple game of chess.
I've got a base class gamePiece, which I'm thinking will eventually become an abstract class ( but right now it isn't)
The base class gamePiece has a bunch of data members in it: colorOfPiece, rankOfPiece, fileOfPiece, etc. It also has a function, void displayPieceInfo() which simply displays all of these values on the console via cout.
I am planning on having a number of derived classes from this one. Right now I have a "rook" subclass.
I want to add various types of pieces in a single vector, so I can later traverse it with an iterator.
Here is the problem I am running into.
vector<gamePiece> vectorOfAllGamePieces;
vector<gamePiece>::iterator itGamePieces;
I push_back a Rook into the vector as the first element. All the constructors look like they are running fine, initializing the variables. Yet when I try to run the display function on the first element, the strings are empty/unitialized.
itGamePieces=vectorOfAllGamePieces.begin();
itGamePieces->displayPieceInfo();
If I were to push in a generic gamePiece into the vector instead, everything would display properly.
Am I allowed to even have a vector like this with mixed types of objects -- for example, an object of a derived class, an object of the parent class, an object of a second class derived from the same parent
And if so, why do you suppose the values of the data members aren't showing up properly, even after I have set them in the constructor?
Not really, because of slicing. When you add a derived object to a vector<gamePiece>, it gets sliced and a gamePiece object is actually added to the vector.
You'll need to use a vector of (smart) pointers.
The problem is like this, Rook is a GamePiece. But You Cannot Store a Rook in a place for GamePieces. You can only cast a Pointer to Rook to a Pointer to GamePiece. So your vector must be saving NOT GamePieces but GamePiece * (Pointers to GamePieces).
std::vector<GamePiece *> vectorOfAllGamePieces;
But this could give you trouble in memory management. Another way is to store Handles without using pointers. ( a handle is something like a pointer to a pointer ). Or of course you can use smart pointers.
A quick hack will be ( this is a "hack" which is "evil" in the eyes of some people ),
std::vector<Rook> allRooks;
std::vector<Pawns> allPawns;
.....
std::vector<Queen> allQueens;
King theKing;
std::vector<GamePiece *> allPieces;
The allPieces will contain pointers to objects in the other vectors.
I think this is kind of OK when you know exactly all the types of pieces ( i guess this is chess ).

C++ allocating space for objects using inheritance

I've got a question about how a C++ compiler knows how much space it needs to allocate for an object when using inheritance.
Imagine the following classes, for an adult and a child which extend a Person class, but where a child has a short book with them.
class Person
{
};
class Adult : public Person
{
//No book
};
class Child : public Person
{
char book[1000]; //Stores the book
};
Now if you create an array of Person objects, and add objects to them:
Adult adult1;
Child child1;
Person people[2];
people[0] = child1;
people[1] = adult1;
My question is:
How does the compiler know how much space it needs to ensure the array is a contiguous memory block, if it doesn't know whether the array will be filled with Adult or Child (which are much different sizes) objects?
I hope this makes enough sense to answer...
Thanks
How does the compiler know how much space it needs to ensure the array is a contiguous memory block, if it doesn't know whether the array will be filled with Adult or Child
The people array cannot contain Adult or Child objects: it can only contain Person objects.
When you perform the assignment people[0] = child1;, what actually happens is the Person parts of the child1 object are assigned to people[0]. All of the Child parts are effectively ignored.
This behavior, where only the base class parts of an object are copied, is called "slicing."
To get polymorphic behavior in C++, you must use either pointers are references. Since it is impossible to have an array of references, you would need to use an array of pointers.
Since your array is of type Person, the compiler doesn't know to declare enough space for children and adults. It just declares enough for two people.
Each time you put in a child or adult, the object will get "sliced" off, keeping only the Person part of the object.
The standard way to get around this is to declare an array of People pointers (which are all of constant size regardless of what they point to, since they're really just memory addresses), which can point to objects of any of your classes.
If you're not creating an array of pointers, Person people[2]; will assign enough space for 2 objects of type Person.
When you'll assign a Child to the Person only the Person traits of Child will be copied.
This is an excellent question.
The answer is that it doesn't. It allocated enough space only for the fields of the People class. When you copy a child into it, only the people parts (hehe) get copied. See What is object slicing?.
If you really want want to do this operation, you should probably be using pointers.
The assignment you've shown doesn't make too much sense. Yes, the array as you show it will be contiguous, but it won't have space for any of the derived class members, and when you perform that assignment those data will be dropped (if the compiler even permits it, which I'm not sure it will).
In a nutshell, there is no such thing as a virtual constructor in C++, when creating an object you have to know exactly what you are creating. Once the object is created, you can use polymorphism derived class specific behaviour from a base class. In your case when creating a Person object only a Person object is created. If Person has a pure virtual method, the compiler will refuse to create it.
In the event that you are unsure whether to create a Parent or a Child Object you can use a polymorphic Abstract PersonFactory although when creating the factory, for the same reason, you will have to know exactly what type of concrete object you are creating.