Passing objects and object oriented design best practices - c++

I'm a university student learning programming. For practice I'm writing a blackjack program. I'm using C++ and doing an object oriented approach to this.
I have a Deck class designed that basically builds and shuffles a deck of cards. The deck generated is composed of an array of 52 Card class objects. That's what I have so far.
My plan is to have a Dealer object, which has a Deck of 52 Cards deal a Card to a second Player object and then deal to the Dealer's own hand.
My first question is: Is it bad practice to make the array of Card objects public in the Deck class?
I ask this because I consider the array an attribute and was taught that most attributes should be made private. I don't want to start using bad or lazy practices in my projects and want to do it the right way.
Another question: How are objects, such as the Card object used in my blackjack program, generally moved from within an object -like the dealer- to a second object like a player?

My first question is: Is it bad practice to make the array of Card objects public in the Deck class?
Yes. In general, data members should always be private. It is good OOP to create an interface with no associated data that defines what operations can be performed on the object, and then to provide a concrete class that implements that interface. The data is an implementation detail that should not be visible in the interface or even in the fully concrete class. As an example of why it is bad, you might implement your class using an array of Card objects right now, but maybe later you decide to use a bitset where a single bit indicates whether the card is or isn't present in the deck. If you make your Card array object public, changing the representation in that manner would break other users of your class; however, if you keep it private, you can make that change without impacting the users of your class.
Another question: How are objects, such as the Card object used in my blackjack program, generally moved from within an object -like the dealer- to a second object like a player?
It depends on whether the other object needs to access the original card object, whether the other object will hold onto the original object for a long time or only a short time, or if the other object is able to handle only a copy of the card. It also depends on whether the card is a concrete class or a polymorphic type, since polymorphic objects can only be passed by pointer or reference (because passing polymorphic objects by value will lead to code slicing). With concrete objects, you have the option to pass a copy unless you need to modify or access the original object, in which case a reference is needed. Choosing the right way to pass objects is somewhat complicated, but hopefully this will clarify:
Pass by value if:
It is a primitive type or small, non-polymorphic concrete type that does not need to be modified.
Pass by constant reference -- that is const T& for some type T -- if:
You do not need to modify the original object.
You do not need to read the original object outside of the scope of the function.
You do not need to read the object beyond the scope of the function, or the type
is non-polymorphic and cheap to copy, so you can create a copy if you need to hang onto
it.
Pass by reference -- that is T& for some type T -- if:
You need to modify the original object.
You do not need to read/write the original object outside of the scope of the function.
You do not need to read the object beyond the scope of the function, or the type
is non-polymorphic and cheap to copy, so you can create a copy if you need to hang onto
it.
Pass by constant smart pointer to a const -- that is const shared_ptr<const T>& for some type T -- if:
You need to read the original object both in the scope of the function and beyond.
You need to read the object both in the scope of the function and beyond, and the type is non-polymorphic so that it is not possible to safely create a copy of it.
Pass by constant smart pointer -- that is const shared_ptr<T>& for some type T -- if:
You need to read and write the orginal object both in the scope of the function and beyond.
I have given each of the above in deliberate order; you should try the first one that will suffice for the job, only moving onto the next if the previous is not sufficient. Also, I should add that boost::call_traits<T>::param_type can help you choose between passing by value and passing by constant reference in the case of concrete non-polymorphic types (it can determine, based on the size of the object, whether pass by value or pass by constant reference is better).

At least IMO, you're trying to overdo it. In reality, a card deck doesn't have any behavior -- it's just a bunch of cards. You don't have a dealer who tells the deck of cards to shuffle itself; you have a dealer who shuffles the deck. I'd do the same in a program -- the deck would just be an std::vector<card> that's owned by the dealer (and it should almost certainly be private).
For dealing, each player would have its own std::vector<card> for its hand. The dealer would then pass each player one card at a time by calling the player's deal (or whatever) member function.

My first question is: Is it bad practice to make the array of Card objects public in the Deck class?
Depends. But it is usually bad to expose data publicly.
This is because public items become part of the interface and thus must be maintained.
It would be better to make the array a private member then expose actions via the public interface. This will then allow you to change the private data later (for instance when you learn how to use a vector you may replace the array with a vector. If the array was public you would not be able to change the type without affecting every other type that used that fact that it was an array).
Principle: Hide implementation details.
This leads to a looser coupling between types.
Another question: How are objects, such as the Card object used in my blackjack program, generally moved from within an object -like the dealer- to a second object like a player?
Remove it from the array in one object (and shrink the array to show it has less cards (thus you may want a container type that can change in size)) Then put it into another array (container) in the destination object.

1) Generally, yes. Conceptually, the Player instances do not mess with the cards belonging to the dealer, so it should be private.
2) One way to do that:
struct Card
{
Suit suit;
Rank rank;
};
class Player
{
private:
void AddCard(Card card);
friend class Dealer;
};
class Dealer : public Player
{
public:
void DealTo(Player& player);
};
Dealer dealer;
Player player2;
dealer.DealTo(player2);

Related

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 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.

Class Objects or Pointers to their Objects? Class object combination and Implementation

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.

How to decide whether class attributes should be pointer or value while using composition in C++?

See this example.
an University class has a Director and many student So my class will be like this
a)
class University {
Director d;
Student list[1000];
};
or
b)
class University {
Director* d;
Student* list[1000];
};
My problem is how to decide whether class attributes should be pointer or value.
Most all other answers focus on the detail of heap vs. direct containment (or provide no information at all, like use pointers when you want pointers... Rather than focusing on the details, consider the overall design of the application.
The first question would be about ownership. In your program, are those students and director owned by the class? Or do they exist outside of the class scope. In most simple applications, the objects might only exist inside the class, but in other more complex designs, the students might belong to the school, and only be referenced in the class (or the director might also teach some courses to other classes). If the class owns the objects, the composition will be the best approach: hold the director directly as a member, and the students inside a container that is directly held by the class (I would recommend a vector, which is the safe choice for most cases).
If the objects don't belong to the class, then you will rather use aggregation. Whoever owns the object will have to manage the lifetimes and decide how to store the real objects and the class would only hold references (in the general sense) to those objects. Things get more complicated as there are more choices. If ownership can be transferred, then you would dynamically allocate the objects and hold pointers, where you should read smart pointers so that memory will be managed for you.
If ownership does not change and the lifetime of the students/director are guaranteed to extend beyond the lifetime of the class, you could use references. In particular for the director. In the case of the students, it will be more complex as you cannot have containers of plain references, so the solution might still be pointers there, a vector of pointers. Another issue with references is that they cannot be reseated, which means that if you hold a reference to the director, the director of the class will be fixed for the whole lifetime of the class and you won't be able to replace her.
Design is somehow complicated and you will learn with experience, but hopefully this will provide a quick start onto your problem.
The issue here is: Where is the storage for these member variables? Sometimes it makes sense that a piece of data was allocated somewhere else and used other places. In that case a pointer may make sense (rather than using a copy constructor). However, usually that isn't the case (especially with encapsulation). Then you want to store the member data in the class. In such a case, and your example looks like it is, you don't want to use a pointer.
how to decide whether class attributes should be pointer or value
I would mostly go for value (i.e. object). In some special cases, I will choose a pointer (may be a smart one!). For your case, below would suffice:
class University {
Director d;
std::vector<Student> list;
public:
University () { list.reserve(1000); }
};
The advantage of having an object is that you don't have to do your own garbage collection as the resource management will be automatic.
Pointers can be used, when you want to change the ownership of the resource (similar to shallow copy), at the same time avoiding expensive copies created during copy c-tor or assignment. In all other cases, use objects (i.e. value) for composition.
Well it depends. Pointers should be used when you want to add stuff to the heap, while this means you have a bit more freedom in when/how you allocate memory, you have to add more code to avoid memory leaks: ie destructors and deleting stuff. It also allows you to easily modify the values from other functions/classes without having to pass a reference, just pass it in its pointer form.
One obvious situation when pointers are totally needed is in a binary tree node object, since it must contain objects of the same type as itself, it must use pointers to those objects. IE:
struct Node{
Node* left;
Node* right;
//Other stuff
};
In many situations however, its up to your own discretion. Just be responsible for your pointers if you use them.
Actually there are three options
1. Object
2. Reference
3. Pointer
It's part of the design/architect .. on what to use for what object.
Mostly .. the deciding criteria will be, lifecycles of the objects and the containers.
In both cases the class attributes are being stored by value, it just happens that in the second case those values are pointers.
Use pointers when you want pointers, use non-pointers when you don't want pointers. This entirely depends on the desired semantics of the class that you are writing.
This is what i would go for:
class University {
Director d;
Student **list;
};
Even though its much of a personal matter. i think using pointer to pointer is better in this case if you know what you are playing with!
I dont think a pointer array is a good choice. If you dont want pointers then use Value

Should the objects initialized and stored in another class be dynamically/statically allocated?

I am new to C++ but I have some basic memory allocation knowledge in C. I am writing a class Card, which stores the card number and a list of class Activity object.
class Card {
public:
Card();
~Card();
vector<Activity> activities;
int cardNo;
}
Currently, I initialize the Activity object using code like:
Activity a = Activity("a");
and push them to the vector defined in the Card object.
But I found people tend to initialize using Activity *a = new Activity("a") instead (dynamically allocation?), and the objects declared in the former way (statically allocated?) will be freed when the function declares them terminated.
Then, if I initialize Activity objects the same way I did before, but initialize Card using the "new Card()" way, is it possible that the Activity objects may have been de-allocated before Card object freed? Should I switch to use "new Activity()" to initialize objects stored in Card?
No, what you're doing is fine. When you push an object onto a vector, a copy is made. So when your function returns, your a is destroyed, but the vector you added it to still has its own seperate copy.
One reason someone might allocate an instance of a class dynamically and push it onto a vector would be that copying objects of that particular class around is expensive (and vector does a lot of copying around internally) and they want to avoid that, so they store pointers instead of objects so that only copies of the pointers are made, not of the objects (which is would not be nearly so expensive). That all depends on the class though; generally you can use vectors of objects without any performance issues.
Note: a shortcut1 for Activity a = Activity("a"); is Activity a("a"), or better, do what Benjamin suggested and do activites.push_back(Activity("a")) if you're not performing some operations on the Activity before you push it.
1 It's not really a shortcut because it does something different, but for your intents and purposes, it is.
"But I found people tend to initialize using Activity *a = new
Activity("a") instead (dynamically allocation?)"
What people? They're doing it wrong. You're doing it right, sort of. You could just do this instead:
activities.push_back(Activity("a"));
A few cases where you need pointers:
it might be NULL instead of some dummy state
it is polymorphic
shared, not exclusive to the class
there is a circular dependency or recursion that prevents a direct member variable
In this particular case, as with most STL containers, member variables are preferred over member pointers.