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

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.

Related

Is there a way to add a pre created class to a vector?

First off, I'm new to c++, currently learning it online.
I greatly appreciate any help...
I have a vector of classes set up for vehicles, however it should also contain derived classes for vehicles of different types (car, truck, van).
My class is set up to have functions to gather user input and assign that to different variables, I do not use the constructor for this. Is that wrong?
In my main this all works fine and dandy but when I go to add the class to the vector I run into issues, first off, My instructor informed us to use smart pointers for this, so I initialize my vector like so...
vector<unique_ptr<Vehicle>> vehicles;
This is how I'm adding classes to that vector...
// For base class...
vehicles.push_back(make_unique<Vehicle>());
// For derived class...
vehicles.emplace_back(make_unique<Car>());
This is where I am stuck, adding the class this way will cause it to be called and therefor the constructor called as well. What I would like to do is just add a class that I have already created and defined beforehand, for example..
// Functions to gather user input, validate and display...
Vehicle vehicle;
vehicle.getMake();
vehicle.validateName(vehicle.make);
vehicle.getModel();
vehicle.validateName(vehicle.model);
vehicle.displayVehicle();
vehicles.push_back(/* Somehow add 'vehicle' */);
Thanks for any help, I understand this might be the wrong way to do this, I was just struggling to find a solution and this is currently where I am at.
My class is set up to have functions to gather user input and assign that to different variables, I do not use the constructor for this. Is that wrong?
A constructor shouldn't do lots of things, and never prompt for user input… but, at the same time, it should not be possible to have a "half-ready" object at any point. I suggest you gather all your user input first, then pass it into the constructor so your object is ready to go in one step.
(I have not shown this in the following example.)
This is where I am stuck, adding the class this way will cause it to be called and therefor the constructor called as well. What I would like to do is just add a class that I have already created and defined beforehand, for example..
Your vector contains unique_ptr<Vehicle>s, so you'll want to start off with one:
std::unique_ptr<Vehicle> vehicle = std::make_unique<Vehicle>();
vehicle->getMake();
vehicle->validateName(vehicle->make);
vehicle->getModel();
vehicle->validateName(vehicle->model);
vehicle->displayVehicle();
vehicles.push_back(std::move(vehicle));
Notice that all the vehicle. are now vehicle->, because vehicle is no longer an actual Vehicle but instead a pointer to one.
std::move is needed because unique_ptrs are not copyable, only moveable.
Taking my advice from the start of the answer, this gets somewhat simpler:
std::string make = GetMake();
ValidateName(make);
std::string model = GetModel();
ValidateName(model);
vehicles.push_back(std::make_unique<Vehicle>(make, model));
vehicles.back()->displayVehicle();
I've moved the displayVehicle call to the end, because it shouldn't make a difference to your output, but allows us to do the "construct Vehicle" and "put it into vehicles" steps simultaneously.
This approach assumes that you have altered your constructor to take make and model, and set up free function GetMake(), GetModel() and ValidateName() to do those tasks.

Creating a unique ID for class types C++

My goal here is to create a unique ID (starting a 0) for each child of a specific class. I'm not sure if it is possible in the way i want, but i figured i'd ask here as a last resort.
Some context:
I'm creating my own 2D game engine and i want it to have an ECS as it's back bone (Before anyone says anything, i'm doing this as a learning experience, i know i could just use an already existing game engine). My idea is that each class that implements the 'EntityComponent' class should have a unique ID applied to it. This needs to be per child, not per object. I want to use this ID as the index for an array to find the component of an entity. The actual ID that each Component gets is unimportant and each component does not need to be assigned the ID every run time.
My hope is there is some way to create something similar to a static variable per class (That implements the Entity Component class). It needs to be quick to get this value so doing an unordered_map lookup is slower than i would like. One thing i do not want to do is setting the ID for every component myself. This could cause problems once many components are made and could cause problems if i forget to set it or set two components to the same ID.
One idea i had was to make a variable in EntityComponent called ID (And a getter to get it). When the entity is constructed it looks up an unordered map (which was made at run time, assigning an ID to each class) for what ID it should have. The price of looking up once at construction is fine. The only problem i see with this is there is a lot of redundant data (Though overall it seems it would account to a pretty small amount). With this, every single transform component would have to store that it its ID is x. This means potentially thousands upon thousands of transform components are storing this ID value, when only 1 really needs to.
Basically i am after an extremely quick way to find an ID for a class TYPE. This can be through a lookup, but it needs to be a quick lookup. I would like something faster than unordered_map if possible. If this can be done through compile time tricks (Maybe enums?) or maybe even templates i would love to hear your ideas. I know premature optimisation is the bad, but being able to get a component fast is a pretty big thing.
What i'm asking might very well be impossible. Just thought i'd ask here to make sure first. I should also note i'm trying to avoid implementation of this in the children classes. I'd like to not have to set up the same code for each child class to create an id.
Thank you.
In order to get something corresponding to the actual type of an object, it either needs to be in the object itself or accessed via a virtual function. Otherwise the type will be determined by the type of the variable it is associated with.
A common option when speed and size are both important is to have an integer identifier associated with each type (when the full type list is known at compile time) and use that integer value in a specific way when you want to do something based on the type.
The integer mechanism usually uses an enum for generating the corresponding value for each type and has that field in every object.
The virtual method variety, I've used boost::uuid and a static data member in each class and a virtual method get'er for it.
Declare a virtual function newId() in EntityComponent.
Implement this function to get and increment a static variable in each class, which children you want to have a unique Id.
Assign Id in the constructor:
mId = newId();
don't know this if this is what you meant and i know this is an old post however this is how im currently dealing with a similar issue, maybe it will help someone else.
(Im also doing this as a learning experience for uni :) )
in the controlling class or its own utility class:
enum class EntityType{ TYPE_ONE = 0, TYPE_TWO =1};
in class header:
#include "EntityType.h"
class Whatever{
public:
inline void getType(){return _type;}
OR
inline void getType(){return EntityType::TYPE_ONE;}
private:
EntityType _type = EntityType::TYPE_ONE;
};
Hope this is helpful to anyone :)

Array within array when loading from a file

My problem is quite peculiar in that I have a solution, but it is in my opinion extremely poor and I am looking for a better one. Here's the problem:
There's a file that needs to be loaded and have characteristics to create a bunch of objects. The object will have 10-12 properties and there will be a few types of objects each one with different characteristics. To make it even more fun, there's one type of object that is actually made up of two separate other objects, but that can be ignored for the purpose of this question. The file will store the characteristics for a few objects as well as the base class. For example the base class will contain the "car" manufacturer, factory made and maybe the engine used, but each of the objects will contain other data unique to each model; model name, tires, or whatever you can think of.
At the moment I have the cars loaded into a map, from the file:
std::map<std::string,std::string> loadCars(std::string filePath);
This way I can just pass this map to each of the objects constructors and it'll look for the key it needs (For example one model might need to check for the types of sunroof used whilst another doesn't have a sunroof, so can ignore it) and initialize the data. It'll load the car model name into the object name etc, like this:
Car ford = new Car(std::map loadCars(cars.txt);
Now here's the problems, from minor to major:
1) If three car models are loaded in and none of them have sunroofs, the sunroof field in the map will be unitiliazed when its passed to the constructors, I dont know if this will cause errors, so I will require a function that pre-initializes the map with empty values, which I don't think is too bad.
2) And here's the major problem and why this solution does not work:
Some of the values in the car file are arrays. Meaning that an std::string in the map will not store them. Now the solution I have at the moment to me appears very ugly:
std::map<std::string, std::vector<std::string>> loadCars(std::string);
So I pass this map to the constructor and for each of the vectors it has to check if it has more than one value. For example model name would not, so it would be hardcoded to put that one value in a string. Or if this particular car only has one type of tire but normally they have multiple types, it'll just put in the vector with one element.
The problem is that when doing the actual file loading absolutely everything will have to be converted from simple strings like the string for the model name into a vector. This seems like a waste and very shoddy code.
Are there any better ways of doing this? Ideally you'd have a map-like container where the second value can either be a vector or a string but I dont think those exist.

reducing duplicated methods?

So I'm working on a 2D space simulator and I have the resource manager 'calc' that handles all calculations for everything. For example, from calc.hpp:
var calc::eccentricity (object A, object B);
var calc::distance (object A, object B);
var calc::orbitV (object A, object B);
etc. However, the way I have my program structured is in my calc class I have
private:
object *ship //the currently controlled ship
object *targ //target
object *ref //reference (from which speeds, position, etc. are calculated)
and to use the calculations given in the first example with these, I write three functions for each calculation function, like so:
var calc::ship_ecc (object A){
if(!ship) //catches null pointers
return NAN;
return eccentricity(*ship, A);
}
var calc::ship_ref_ecc (){
if(!ref) //catches null pointers
return NAN;
return ship_ecc(*ref);
}
var calc::ship_targ_ecc (){
if(!targ) //catches null pointers
return NAN;
return ship_ecc(*targ);
}
for eccentricity, and then the same for distance and orbitV. So I end up having four functions for every calculation. As you can see from calc.hpp this makes for plenty of duplicated code. And duplicated code is a Bad Thing.
What my question is
Is there some way to call
calc.ship.targ.eccentricity();
calc.ship.ref.eccentricity(); //or variation thereof
or
calc.ship.targ(eccentricity);
calc.ship.ref(eccentricity); //or variation thereof
instead of
calc.ship_targ_ecc();
calc.ship_ref_ecc();
? I'm wondering if you could do some fancy operator() overloading, or pass a function, or make a friend class in calc. Ideally I should only be able to access lines 31 - 53, which are all public.
Thanks!
EDIT: got an example for yall: https://ideone.com/jypJQS this is what it should output and how it is working now
Maybe this changes too much your current code. But I think that the functions in calc should be members of object. So you could things like :
ship.eccentricity(target);
What confuses me (and what is probably the big problem here) is that you seem to define some hard relations in your calc object (the private members). What are those for ? From the code, I guess there is a calc object for every "ship". If yes, it would be an other reason to add the code to object instead of maintaining 1-1 relations between object and calc.
This might require a little bit of refactoring, but I think it's worth it. For a simple game, you can use OOP and Polymorphism to fix the issue.
First of all, create an object class.
class Object {
public:
Object();
~Object();
};
This object class would be a basis for all your objects in the game (ship, character, etc...). You, then, would create a sub class for your ship.
class Ship : public Object {
};
This would allow an easy expansion to future objects that require the same principle.
In the object class, you would have some basic properties:
physical (optional)
dimensions
speed (last calculated speed)
controlled (bool - current controlling ship or not)
This would eliminate the need to have hard relationships with the calc and ship class.
Next, you would change your calc class to become general. You don't want to depend on a single ship object, this is cumbersome.
Option 1
You could create an instance of the calc class for each object. This calc instance would have access to the already available properties of the object and ship class.
Option 2
Create a general calc class that would require you to pass a reference to the ship/object instance. calc->eccentricity(&ship, target);
Option 3
Within a possible manager class, or a simple "global" variable. You could hold a reference to the currently controlled ship (if that's how your system works, I'm not sure). Or you could store the index of the ship and all instances are held inside a vector<&Ship>.
In a simplistic game, straight forward OOP will suffice, but if you want more decoupling, component based game design would be a better bet (in combination with OOP, of course).
So I took this over to /r/learnprogramming, and I got a good answer from zzyzzyxx (as always). His answer:
What's wrong with simply having functions that take the required two or three parameters? They don't have to be in any special calc class. Maybe a calc namespace. I'm not sure it makes sense with the rest of your design, but what about making it a member function so that anything can calculate what it needs given a target and potentially a reference point if there's no sensible default?
So basically, don't worry about all this calc.eccentricity(A, B), calc.ship_ecc(A), calc.ship_ref_ecc() business, just say
calc.eccentricity(*calc.targ(), B)
Also, don't make calc a singleton, make it a namespace.
I'll go do that now.

Having an instanced, derived class put a pointer to itself into an array?

Okay so here's a real mess of a question - I don't even entirely know what to search for.
I asked a question here, related to a game's entity handling system: Initiating a derived class with specific variable values
So far, that's working out great for me, but for one thing. I want to have mobs not just collide with eachother, but interact.
How can I look up a specific instance of the derived class, by coordinates?
For example, find the baseObject:Enemy() located at 22,22 and get the value of "nType" from within it
What comes to mind is putting some kind of pointer to an instance in an array, and moving it when said entity moves... but how do I make a derived class add a pointer to itself to an array? and how do I then pull something from that instance's variables?
Whew. Hope this makes sense.
Well, I think a solution to this problem is to use delegates/event passing.
Let's say you have a mob, as someone said earlier you could have a "mob watcher" object. The idea is that when a GameEntity is part of a mob, that entity subscribes to the "mob watcher". If that entity leaves the mob, it will let the "mob watcher" know about it (unsubscribe).
So, when you need to know, who's composing a mob, you could just ask the mob watcher for the "mob list", if you need to search by Entity position you could then work yourself through the list of entities composing the mob, and find the one in the "position of interest".
If your mobs are gigantic you could add some kind of spatial hash feature to your mob watcher, so you could easily filter and ask for "guys in the mob which are located in gameGrid[10][13]".
If you use event passing, it's quite cool because if when you want to forward messages between the mob, sending an event to the mob watcher could be used to then forward the aforementioned event to the subscribed entities.
If you use delegates, it works in a similar way.
Observer Pattern
Delegate Pattern
Well, the specific question you're asking is easy to answer: the pseudo-variable this is available in all member functions; it points to the current object.
The "looking up by coordinates" part is trickier; you might consider using an octree structure to organize your objects (Google is your friend there.)
You will need to make a new object whose job is to keep track of where the "mobs" are. According to your question, this new object will need to contain at least a std::vector which contains a pointer to each "mob" in the world, and also a member function like:
mob* findEnemy( int x, int y );
Unfortunately, what you asked for in your question is probably not what you want. You probably want to get all of the "mobs" near a point:
std::vector<mob*> findEnemiesNearPoint( int x, int y );
...but returning a std::vector can be very slow, so you probably want an array instead, but the array must be sized carefully, and now we're far far beyond the amount of information provided in your question so far.