I am designing a game in which some players cards are known and some aren't. To do this, I made a parent object "Player" with children "OpenPlayer" and "ClosedPlayer".
I want to make an array of all the players in this game to facilitate game management. However, I also want to be able to access the special methods in OpenPlayer and ClosedPlayer as appropriate. Is this possible?
Edit: I am actually thinking of using a vector from STL as this would likely be more appropriate due to variable number of players.
In general, you can't make a C++ array whose elements are of different class types; each array element must be the same size, and that won't necessarily be true of different subclasses. Putting different types in the the array can result in slicing, which is the surprising disappearance of the data members of a subclass.
But if you make an array of pointers to your different subclasses, then you'll easily be able to do what you want. You might also consider using a vector instead of an array if the number of players can vary.
By "access special methods" I assume you mean methods in just the OpenPlayer or just the ClosedPlayer?
By array, I assume you mean some STL collection ;-)
The short answer is "No".
The long answer is "Yes you can, but you'll need to cast objects to the correct type. This implies that your design is wrong."
A different disign might be to make "Open" or "Closed" a property of the Player class rather than individual subclasses.
Related
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 think this question is best explained in the context it came upon me. If you disagree, jump to the next horizontal rule.
I'm developing a virtual board game as a way to improve my C++. Right now I'm facing a problem.
There are several tiles in the game ("spaces" in which you can be in), each one of them can have several monsters in it. Because of the features that I aim for, it is necessary to know which monsters are in each tile and also in which tile is each monster.
This makes me wonder: should I introduce an array in the tile class that will hold pointers to all monster in that tile, or is it better to introduce a pointer in each monster that points to the tile they're currently in? Or maybe both at the same time?
Or, more abstractly:
Objects of type 'A'can relate to zero or more objects of type 'B'. Objects of type 'B' can relate to one and only one object of type 'A'. Given that efficient searches must be done either way (find out which 'B' objects a specific 'A' object is related to and, conversely, which 'A' object is a specific 'B' object related to), what is the best way to implement this behaviour?
If this is in any way unclear, ask me so I can provide further explanations.
Here A and B refers to the name of the objects -- be it a pointer, smart pointer, guid into a table, or whatever.
You create a map from A to Bs (zero or more Bs), and an entry within each B specifying an A. The map from A to Bs could be a simple vector<B> within instances of things named by As, for example, or a space partitioning tree of the space that the things named by As are in, or an unordered multimap, or whatever.
Determine where lifetime management should go. Determine if you want weak pointer like behaviour, or dumb pointer like behaviour, in your names. The second requires manual cleanup at lifetime end: the other defers that work to point of use.
I have a set of small objects. Each of these objects points to other objects. These pointers might be realized as actual pointers or as index into an array of the objects or something else. It might be an array of such pointers whose length might change. There might be pointers to objects of the same type and to other types, but this is known at compile time.
So, for example: I have a class Person. This person has two pointers to its parent Persons. There's another class Place. Each Person has a list of pointers to all Places he/she has visited.
In contrast to an actual family tree, I might want to change the tree from time to time by deleting/inserting some Persons.
Is there a container in the C++ Standard Library (C++ 11) for that purpose or should I better look for a dedicated memory management class?
I will have to pass the data to a C interface why I would prefer a storage method which is based on an accessible (read only) linear array.
Sounds like a great time to quote Stepanov:
Use vectors whenever you can. If you cannot use vectors, redesign your solution so that you can use vectors.
The "accessible linear array" part points to vector<Person> - none of the other containers have that feature - and the rest of your use-case doesn't suggest any specific kind storage or access. Part of it sounds like it might be cleaner if you could do vector<shared_ptr<Person>> but that would break your C interface requirement. So vector<Person> is probably your answer.
Questions:
"There might be pointers to objects of the same type and to other types, but this is known at compile time."
"These pointers might be realized as actual pointers or as index into an array of the objects or something else."
In contrast to an actual family tree, I might want to change the tree from time to time by deleting/inserting some Persons.
"Is there a container in the C++ Standard Library (C++ 11) for that purpose or should I better look for a dedicated memory management class?"
"I will have to pass the data to a C interface why I would prefer a storage method which is based on an accessible (read only) linear array."
Answers:
This could become difficult if you want to use pointers to multiple types of objects in a single container. But you could make either a raw array or a std::vector work.
If you're just using indices that would greatly simplify your "pointers to multiple types" problem. Again either a raw array or a std::vector work.
Dynamically changing raw array sizes gets sketchy fast, I'd say this is a point for std::vector.
Depending upon the time that you are willing to put in, managing your memory is a tremendous endeavor, I'd stick with a raw array or std::vector until they pried my cold dead fingers loose.
If you have C++11 using std::vector::data can make a std::vector just as usable as a raw array here, if not this would be simpler to implement as a raw array.
std::vector has numerous benefits to you as the programmer. Not the least of which is automatic memory management. So I'd lean toward std::vector where it is an option.
I prefer to use vector rather than other (list, etc) . as Bjarne said "If you know int and vector, so you know C++".
Here is the link at Youtube, as Bjarne said about vector:
Bjarne Stroustrup: Why you should avoid Linked Lists
Background of the issue
I'm working on a basic battleship-like spinoff game that I want to continue to add features to over time in C++ (no graphics). Currently I have a 50 x 75 game board, represented with a 2D vector (called GameBoard) that is currently of type char. I create a game board and set each location with '.' char. As you guess coordinates, previously guessed locations are marked with '-' and hits are marked with 'X'
Where I'm at with the program
I decided to modify the game to enable some more features. I'm not too far along, but sketching up a design in pseudocode started making me think more about how I can go about this upgrade.
Instead of the GameBoard being chars, I'm creating a class called Block (an empty space on the board), which will now have a x and y coordinate variables, along with a char variable to visually display the correct char. Block has the ability to hold the object "Feature" which breaks off into derived classes of "feature." You can scroll to the very bottom for more detail about these classes.
This is how my class hierarchy tree goes:
feature
item vehicle
gold nuke plane
What I need help with
I basically have the outline/structure setup for what I want to do. Now I just need some help kickstarting it to get everything to connect. I'm pretty bad with determining when and how to use pointers.
A.) Should I change GameBoard to hold pointers of the Block class? Or actual Block objects?
- And would Block hold a pointer to a Feature or the actual Feature object?
B.) How do I add a Feature variable that can be empty or given a value? Do I just set it to NULL?
C.) Do I need a custom copy constructor to swap the Feature value of Block?
D.) How do I go about removing the Feature object from Block if the player uses it?
E.) Can there be more than 1 Feature on a single Block occasionally?
F.) How do I declare the Block and Feature classes such that Block can hold a Feature and Feature is already derived from another class (not included in this post).
Extra Details about my classes
So GameBoard is the vector that will store Blocks. Blocks are essentially the individual spaces on the board. Block contains coordinates for its location, a char to represent it, and the possibility to hold a Feature object, but most of the time the Block won't be holding a feature. Feature is derived from Block and acts as a bonus reward in the game. So Feature branches into 2 more derived classes, an Item Feature or Vehicle. And so on.
When the player chooses coordinates, a method will go to that Block on/in the GameBoard and first check if the char value represents a valid space that hasn't been used before. Then it checks the contents of this Block for Feature. Feature may be empty or contain a derived Feature object.
Ok that concludes my novel. Sorry for writing so much. I figure the best way to get help is to let the helpers know what's going on. PLEASE don't respond telling me to "get to the point." I know I know.. Let me know if I'm missing details. Thanks!
I am assuming you want to keep your class structure. At your point of abstraction I am suggesting using shared and uniqe pointer via (C++11 or Boost). If you're pretty bad at pointers learn how uniqe and shared pointer work and try to stick with those. Remember to keep the object's life scope as short as possible.
A.) Should I change GameBoard to hold pointers of the Block class? Or actual Block objects? And would Block hold a pointer to a Feature or the actual Feature object?
I want keep this GameBoard elements as immutable uniqe pointers or keep actual instances.
B.) How do I add a Feature variable that can be empty or given a value? Do I just set it to NULL?
You have decided to keep Feature inside Block - ok. If so keep it as shared pointer. If there is no feature shared pointer will be empty.
C.) Do I need a custom copy constructor to swap the Feature value of Block?
Only if there is something dynamic/unusual inside Feature. What will the Feature hold?
D.) How do I go about removing the Feature object from Block if the player uses it?
If you use shared pointer there's no problem. Even if the Feature have changed during handling previous Feature, Feature will be handle correctly and destroyed when it's no longer required by GameBoard.
E.) Can there be more than 1 Feature on a single Block occasionally?
You have to ask yourself this question - does your game require handling this situation? If so simply hold vector/map/set/array (depending on your requirements) of shared pointers to Features.
F.) How do I declare the Block and Feature classes such that Block can hold a Feature and Feature is already derived from another class (not included in this post).
I am not sure if I understand the question correctly:
class Feature : public GameElement {
/* Feature implementation */
}
class Block {
shared_ptr<Feature> mFeature;
/* Block implementation */
};
Does it answer your question ?
I am not sure if it is a good idea to derive class feature from class block
I would rather use a pointer to feature within each instance of block, this way the pointer is NULL if there is no feature. This pointer would be pointer to the base class feature in your case. I encourage use of virtual methods to access individual features.
when a feature is used up, delete it and set pointer to it to NULL. (the pointer that is within the block instance)
if you want to have more than one feature per block at a time, consider using some kind of array/stack of pointers.
in my opinion the GameBoard should hold actual instances (not pointers) of Blocks.
I do not understand what do you mean by:
Do I need a custom copy constructor to swap the Feature value of Block?
I hope this helps =).
I think it would be a good idea of your GameBoard is a container for GameObject pointers. You don't need to create a whole new class and call it Block - all this is implied. There is also no need to track the coordinates of blocks, since they are arranged in order. A GameObject would be the base class for the hierarchy of game elements - in your case that would be a Feature, the reason I used GameObject is because Feature is just not very descriptive - the term is too broad with wide scope.
When the game is started, your GameBoard can be populated by null pointers which are subsequently substituted by the actual game elements that are created and added to the board.
You only need to implement copy constructor and assignment operator if you have dynamically allocated data. If not, the compiler will generate a perfectly good version that will do raw object copy.
That being said, you'd better not move actual object instances around, and with the proposed method of using pointers instead, you will only be moving pointers, which is much simpler and faster.
If you want to remove a Feature, just delete the actual object and set its pointer in the board to null.
If you implement a parent/child relation you can have a tree of GameObjects in each block, and you can traverse that tree recursively and do to the tree elements as you will.
A well designed polymorphic hierarchy will allow you to put pretty much anything as long as it is derived from your base class.
I have a data structure that stores ... well, data. Now, I need to access various pieces of data in slightly different manner, so I'm essentially building an in-memory index. But I'm wondering: should the index hold pointers or copies?
To elaborate, say I have
class Widget
{
// Ways to access the list of gears...
private:
std::list<Gears> m_gears;
};
Now, I have two Widgets, and there exists between these two a mapping between their Gears. Currently, this is
boost::unordered_map<Gear, Gear>
but Gear is a fairly hefty class, and I feel like making so many copies is poor design. I could store a pointer, but then the mapping is only valid for the lifetime of the corresponding Widgets, and you start getting ->s... (And if that std::list ever changes to a std::vector, it gets more complex...)
Pertaining to the copies, it's actually slightly worse: There's two boost::unordered_maps, one for each direction. So, for each Gear, I'm making up to 2 copies of it.
Alternatively, I could put the index inside the Widget class, but I feel like this violates the responsibilities of the Widget class.
You might try Boost Pointer Container Library: http://www.boost.org/doc/libs/1_43_0/libs/ptr_container/doc/ptr_container.html
I think it addresses exactly the problem you are facing.
Could you store all gears in one place, like statically in the gears class, and then have each mapping AND widget store only the reference/index to it?
You would have to keep track of references to each gear so you know when you can dispose them, but that should be easy enough.