A list containing objects of two different classes in C++ - c++

I feel more fluent in Java than C++ so I will try to explain what I want to "transport" in a few words. In Java you could create an ArrayList containing objects of 2 or more classes that one of them inherited from another. Let me illustrate. Let's say we have:
class Vehicle
{
...
}
class Car extends Vehicle
{
...
}
You could then do something like that Car a = new Vehicle ([arguments]);
And then you could add objects of both Vehicle and Car to the same ArrayList created as following:
ArrayList ar = new ArrayList<Car>();
Now to my problem, in C++ I have manually written the code to create a simple linked list. Each node of this list is described below:
struct clientListNode
{
vip* cust;
struct clientListNode* next;
};
vip is another class which is derived from customer.Is there any way to allow my list to accept both objects of vip class and customer class?

Polymorphism works the other way. You can use a customer* pointer to point to a vip object, but not the other way. (This is related to the Liskov-substitution principle.)
So if you had a customer* in your clientListNode class, it would accept both vip* and customer* pointers.
However, I don't think you should reinvent the wheel and implement a linked list from the ground. You should look into the STL (Standard Template Library) which already has solutions for problems like this. For instance, it already has an implementation of the linked list, std::list.
You have to template std::list with the base type you'd like to use it with, but it is important that you cannot use the type directly as a value (std::list<cust>), because that would physically store cust instances in memory, in which you cannot fit the more specific vip type (slicing would occur).
Instead you have to use some kind of handle as the template parameter, you can use a native pointer (std::list<cust*>), but that way you have to manage memory deallocation, or - more preferably - you can use a smart pointer, like shared_ptr (std::list<std::shared_ptr<cust>>), that way the created objects are going to get destroyed automatically.

I doubt you could make Car = new Vehicle even in java, but the other way around makes sense.
What you're after is called "polymorphic collection". C++ standard lib does not have one out of the box, but you can approximate it with a collection of shared_ptr<Vehicle> s or unique_ptr<Vehicle> s. The former would fork very close to a java equivalent.
3rd party libraries may have ready to use polymorphic collections, you can use the term for search.

If customer is the base class, then the cust field of the node should be of type customer*, and it will gladly accept both customers and vips.

Related

Are there pros to inheriting a class template?

I'm new to c++ and I have more of a "design" question than actual code:
I'd like to write a program that works with many different types of graphs, however I want to support any type of vertex or weight (i.e the vertices are strings or char and the weight can be int,double or char or even a class).
For this cause I wrote a class template of graphs, which contains things like a set of vertices and a map with the edges and their weights and get/set functions - Then I have other classes such as finite-state machine graph, a regular weighted graph etc. which inherit from the class template "Graphs". (in each graph I know exactly what types the vertices and weights will be)
I did this as it seemed natural to expand upon a base class and inherit from it. It works so far, but then I thought whats the point? I could simple create in each class one of these generic graphs and use it as I would use an ADT from the STL.
The point being, is there any benefit to inheriting from a class template instead of just creating a new object of the template in the class (which itself isn't generic)?
According to the explanation you gave above it would be incorrect to inherit the generic graph. Inheritance is a tool to help expand an existing class of the same type to one with additional attributes, methods and functionality.
So, if all you're going to do is take the generic graph and make it a specific one by specifying the type of edges and weights without adding anything else to the structure or functionality of the original class then inheritance is unnecessary.
That being said, there are many cases for which one might need to inherit a template class and either keep it a generic one or a specific one depending on the task at hand. For example, if you were given the task of creating a class that represents a list of integers with the regular operations on lists and in addition to implement a function that return (let's say the average of these numbers or any other operation that is not supported by the original generic class List). In this case you inherit Class List and add your method.
Similarly, you could've kept the List as a template class and added the required functionality if that's what the task requires.
Your question is very broad and highly depends on your particular situation. Regardless, assuming that your question can be simplified to: "why should I use inheritance when I can just put the object inside the class?", here are two objective reasons:
Empty base optimization: if your base class X is empty (i.e. sizeof(X) == 0), then storing it as one of your derived class's fields will waste some memory as the standard forces every field to have its own address. Using inheritance will prevent that. More information here.
Exposing public methods/fields to the user of the derived class: if you want to "propagate" all your base class's public methods/fields to the derived one, inheritance will do that automatically for you. If you use composition, you have to expose them manually.

C++ - trying to point each sub-class to the main class in order to contain all information in a vector

Basically, Im writing a small database/inventory system for a game. The item class and its sub-classes (weapon, armor, consumable, etc) are all finally up and working. My vector for inventory is written within a separate inventory class (allows more than one inventory - i.e. enemies can have them too!) and at this point, the inventory is FAR from written - there is still no drop function, etc.
but im taking this one step at a time because its a learning experience.
basically I believe in this case, pointers are the answer. this code seems to work (have not tried it yet)
Weapon DebugDagger{ 1, "Debug Dagger", "Debug Dagger given to you by Help", 25 };
Armor DataCloak{ 2, "Data Cloak", "Data Cloak given to you by Help", 10 };
Item *pItem = &DebugDagger;
Weapon *pWeapon = &DebugDagger;
InventoryManager PlayerInv;
PlayerInv.pickupItem(pWeapon);`
in this case, pickupItem(Item*) is taking a static Item type - which is the base class for my function, where the weapon being added to the inventory is a sub-class (class Weapon : public Item{})
the way this is written seems to hack together a solution, but it would be MUCH easier if I could just write the pointer into the class functions themselves so that EACH item created in a sub-class automatically will create a pointer of itself to the base class so I can add it into the inventory subsystem. Is there a way to do this from Within the class? so that EACH member gets a pointer created automatically upon class creation? When I try to use the name variable in the constructor to do this, it does not work, as it seems I have to create the member BEFORE making a pointer, so I dont see how to do it at the same time anticipating a new member being created.
I mean, I'm all for other more effective ideas than a std::vector inventory; for an inventory - I think some function that actually can simply accept the members of any class and record them would be FAR more effective in the long run, but I do not believe this is possible - I think that creating pointers to Item from the sub-classes would still be necessary - seeing as, really, its all items, with each sub function having a single extra specifier ONLY being used for its own function, weapon has attack, consumable has restoration, etc -and its ALL integers, so really those are the same as each other almost, but for function reasons, like equipping, using, classifying, they each get a separate type I suppose I couldve made a SpecialItem subclass to cover it all, but that would be very ambiguous, and leave little room for innovation should a specific type need modification later.
I just dont see it if there is an alternative. if there is direct me and I will read voraciously until I find understanding of it.
Not sure if i got the point, but a pointer to the subclass (Weapon) is already a pointer to the base class (Item).
So you can store all your items (Weapon : Item, Arnmor : Item, ...) in your
std::vector<Item*> Inventory
It does not seem to work this way, because by default NO pointer is being created, in this instance I Had to write one on the fly after creating the Item in order for it to push_back.
otherwise it tells me class Weapon cannot be converted to Item * and wont compile.
so it seems to me that I CAN"T store them into the vector -- for that to work it would have to be
std::vector<Weapon*> Inventory
basically I need the functionality of
std::vector<Weapon*> Inventory
std::vector<Armor*> Inventory2
std::vector<Consumable*> Inventory3
std::vector<Item*> Inventory4
except I need it in ONE single inventory class...
my problem is right now I ONLY have
std::vector,
and NO other class type is ALLOWED to be inserted into this slot, because I have to either convert the type manually (since memory can't do it on its own, the special characteristics have to be dropped), or create a pointer to Item* so that when I insert the POINTER like this:
Inventory.push_back(POINTER);
it will BELIEVE the weapon is an Item, and go ahead with the operation.
otherwise
Inventory.push_back(WEAPON), etc do not work... only Inventory.push_back(Item*)
I dont know if this has been any more clear, but it should make it understandable why I need the pointer. Since I cannot cast a Weapon or even a Weapon * as an Item, I have to create a pointer to Item somewhere in the class function, so that way I have some variable I could automatically pop into the push_back function INSTEAD of the member of the class itself - I sort of have to cloak a weapon or potion as a basic item in order to get it to fit into the vector, because it only accepts basic items as is.
Well, either way - the code ended up being NONFUNCTIONAL IN ENTIRETY.
regardless of this, I need a way to create a database of all members of each type of class.
I need the functionality of a vector, that will work with any type -- or a method to get a vector to accept any type.
I gave up on this method, because it just will not work to have one vector alone.
now Im working on a 3 vector class of obtained item names, quantities, and IDs.
it seems a bit** to figure out how to associate the 3 and also scan through them in unison to make data make sense (I.e. see if item name x, id 32 is in inventory, if it is, allow user to examine such item for details).
this is my first big project really. its a doozy for me.

array and object declaration

I'm trying to create an array list of objects. I am a student and my professor requires that all declaration are before the executable code and that all instantiations or initializations (not sure which term) are done in the executable code. I'm new to the List or ArrayList concept and i can't quite figure out how to get this started.
List <Room> roomAry; //declare array object for rooms
//initialize room array
roomAry = new List<Room>();
This keeps telling me it can't compile.
The error follows:
List is abstract; cannot be instantiated roomAry = new List
();
Because it should be roomAry = new ArrayList<Room> (). It's correct for both .NET and JAVA.
List is just an interface (JAVA)
The error is telling you exactly what the problem is. The List is an interface and is thus abstract. You cannot create an instance of an abstract class or an interface; you always have to create an instance of a concrete class.
Please see the All Known Implementing Classes: section under the List interface in the javadocs. (Note that if the implementing class itself is abstract, then you cannot use it)
So you can use one of the implementing classes for the instantiation. One of the simpler ones is ArrayList.
roomAry = new ArrayList<Room>();

C++ Extending an Array Class (OOP)

Is it possible to derive a child from an array Class?
What I am playing with right now is:
Creating an array of Linked Lists
I am building a List class from which I can derive different types of lists (ie. Linear, Circular, Double Linked, etc...
What I would like to do is to extend an array class to make a "arrayOfLists" class. Then I would take the child class and add to it a LinkedList object member.
Is this possible? Am I even thinking of OOP correctly in this instance?
Thank you for your help
The fact that you're talking about it as an arrayOfLists class is a pretty good clue that inheritance is the wrong tool for this job.
Inheritance (public inheritance, anyway) should only be used when the derived class can be substituted for the base class under any possible circumstances. In other words, that an arrayOfLists could be used anywhere a List could be used. Although that might be possible, it seems fairly unlikely.
It sounds to me like what you want is really just an array-like template (e.g., std::vector) instantiated over one of your linked list classes.

Call method of derived class

I'm doing a program that manages a collection of items. That can be a Book, a Magazine, a CD or a DVD. Each of those is a class thats inherits the class Item. To store those items I'm using the list template, like this:
list<Item> items;
and this list is inside an object lib of the class Library.
To run through this list I'm doing this:
for(list<Item>::iterator i = lib.itens.begin(); i != lib.itens.end(); ++i)
Until this point everything's fine. The problem starts when I try to call a method of the derived class inside this loop. example:
for(list<Item>::iterator i = lib.itens.begin(); i != lib.itens.end(); ++i)
(*i).lib.itens.show();
How can I call those methods?
There are at least two problems here. Firstly, if you do this:
list<Item> items;
then this list really will only contain Item objects; if you try to put in a derived object, the derived part will simply be sliced off.
One solution is to use a list of pointers instead (although you should probably use smart pointers to avoid memory-management issues).
But even then, the second issue is that you shouldn't (in general) be trying to call derived-class-specific methods via pointers to the base class. The whole point of polymorphism is that you should only be dealing in terms of base-class pointers if you're happy to work with functionality that's common to the whole hierarchy (see Liskov substitution principle).
You probably should have defined virtual void show() = 0; in class Item. That would have made the show call legal, but at the same time would have resulted in an error on list<Item>.
The fundamental error is that you can't have something that's "just" an Item, yet list<Item> would attempt to make a list of precisely that. By declaring show as a pure virtual function in Item, the compiler explicitly knows this.