I'm working on a game / simulation, and dealing with managing all the creatures in the game.
There is one base class Creature from which different kinds of creatures take inheritance from.
In early versions of this code, where I just used the base class on its own as a generic for any given creature, I had a private static vector that kept a phonebook if you will of all the creatures that exist in the game. This was handled by the Creature's constructor, adding the new creature's address onto the stack. Simple enough.
Where I'm getting a mental block is when I introduce inheritance. If I proceed to adapt the Creature class to be a base class (move the vector to protected status I would imagine?), and from there define some arbitrary child classes of Monkey, Bear, and Tiger... When I create an instance of a class that inherits from Creature, will it -also- be added to the pointer vector in the Creature parent class? Perhaps more directly, does creating an instance of one of these child classes also call the constructor of the parent class?
Am I on the right train of thought, or what would I have to do to achieve this behavior?
I can provide more specific details if needed.
Thanks.
--
My idea behind doing things this way, for one example is graphics. That way I can cycle through all the creatures that exist and via polymorphism call functions on each of the creatures that return their sprites, X Y location, etc.
This definitely works, as long as your vector store pointers Creature* and not Creature inside your std::vector. Otherwise object slicing would occur since the vector reserve the space for just Creature and every additional feature of subclasses is discarded
Regarding the constructor call stack it is fairly straightforward:
class A {
private:
int aField;
public:
A(int aField) : aField(aField) { }
};
class B : public A {
private:
int bField;
public:
B(int aField, int bField) : A(aField), bField(bField) { }
};
Related
I have a class Game with class EnemyManager. EnemyManager deals with spawning of enemies and the logic behind it. The problem is that EnemyManager needs access to functions and other Game objects in the game class. I can think of two ways to handle this.
Pass the address of the class object Game* using this as one of the arguments in the EnemyManager.
Declare a global pointer to a Game object and set it when initializing the Game class. Then extern it into the enemymanager.cpp.
Which is the more advisable way to do this?
Whenever I encounter situations like this I review the overall design of the related classes. If EnemyManager is a member of a Game object and needs to call things within Game, maybe those functions in Game can be factored out into a separate component. If something you are writing is beginning to feel overly-complex or like a hack it's usually time to do some factoring.
When dealing with object oriented designs, it is typically good to think about who will act how on what to find a first version of a design. After having written this version, one often finds the weaknesses and rewrite it for the second iteration.
So, in this case, the Game class manages the world (I assume) and offers different ways to manipulate it. Your EnemyManager manages one aspect of the world, enemies, but they do live inside the world.
class Enemy {
public:
Enemy(Location& location, int hitpoints);
bool Move(Direction& direction);
};
class Game {
public:
bool CreateInitialState();
bool AddEnemy(Enemy& enemy);
bool AddBullet(Location& location, Direction& direction, int speed);
void Render();
};
class EnemyManager {
public:
EnemyManager(Game& game);
void MoveEnemies();
};
In this first version, all types see each other as proper classes and manipulates things by calling the appropriate method. This offers little support for expanding on the game if you want to add new things to it.
This is where interfaces become handy and you can try to think about how the different parts will interact instead of how they should be implemented.
class Canvas {
public:
// Different graphical primitives.
};
class GameObject {
public:
virtual ~GameObject() {};
virtual void Draw(Canvas& canvas) = 0;
virtual bool Move(Direction& direction) = 0;
};
class GlobalState {
public:
virtual AddGameObject(GameObject& gameObject) = 0;
};
class Game : public Canvas, public GlobalState {
public:
bool CreateInitialState();
void Render() {
// Send itself to the Draw method in all GameObjects that have been added
}
// Other game logic
};
class Enemy : public GameObject {
// This can be specialized even more if you need to
};
class Bullet : public GameObject {
// This can also be specialized even more if you need to
};
This separates design from implementation and, as I see it, is a good way to end up with a proper first attempt.
It is hard to say without knowing the overall architecture layout, but my 2 cents:
The way you describe as a first one is called the dependency injection and is widely used all around. You should keep an eye on what methods/fields you're making public.
I assume that Game class has the methods that should not be accessible from the EnemyManager class, thus is seems like it's a good idea to create the interface which has the declaration of the methods that are used by EnemyManager and then pass the pointer to the EnemyManager instance (instead of the Game).
For example: The Game class implements IGameEnemyManager, and you're passing IGameEnemyManager using this as one of the initialization arguments.
If you are handling game objects in EnemyManager, why is it part of the class Game ? I suppose you should consider reviewing your design as there are chances of circular reference problem if you don't handle the scenarios well.
Consider segregating both the classes to ensure a single responsibility principle.
Define proper interface in yourEnemyManagerto Game object as argument and act on the functions
These are little suggestions that I can think of with limited idea about your design
You're absolutely need to use the 1st approach, but with a few changes: you should disintegrate your Game class to more components. For example you can create a SceneManager class, which is responsible for all game object's creation/management. When you're instantiating the EnemyManager - just pass a pointer to it:
// in SceneManager
EnemyManager* emgr = new EnemyManager(this);
InterfaceManager* imgr = new InterfaceManager(this);
Note that your SceneManager class should provide a complete interface
// in EnemyManager
GameObject* spawnEnemyAt(string name, EnemyClass* eclass, Vector3 position, AIBehaviour* behaviour)
{
GameObject* myEnemy = smgr->createGameObject(name, position, etc...);
//register an enemy in the enemies list, initialize it's behaviour and do any other logic
return myEnemy
}
This approach should help you not to ruin your architecture and not to be captured in the friend(class)-zone.
[Upd.] Note that my approach assumes that all objects on the scene are GameObjects, there's neither Enemy nor Player classes. Every GameObject may has a Renderer, Animator, AIBehaviour components.
I saw that many people use new to create instances of the derived classes and then they keep a pointer to base in some container. Does that have any advantage with respect to using a container for each derived class?
With this I meant something like the following
class A
{
public:
vector<Base*> bases;
set<Derived1> der1;
set<Derived2> der2;
//other stuff
};
Edit: removed the second part of the question and added as a comment.
If you do the following
vector<base*> bases;
You can then use polymorphism on your objects.
Imagine that you have a base class named Vehicule. It has a move() method to go from point A to point B.
class Vehicule
{
public:
virtual void move(){}
}
Then you have two derived classes : Car and Submarine
class Car : public Vehicule
{
public:
void move()
{
checktires();
drive();
}
}
And your Sub class
class Submarine : public Vehicule
{
public:
void move()
{
submersion();
propulsion();
}
}
Because the move method is a virtual one, you'll be performing polymorphism. Which is a mechanism that allows you to call the same function but have different behaviours based on the dynamic type of your objects.
I'll try to explain that sentence the best I can.
Now that you have the Vehicule, Car and Submarine classes, you will create an array (or a stl containers like a vector) of Vehicule pointers.
std::vector<Vehicule*> objects;
objects.push_back(new Car());
objects.push_back(new Submarine());
objects[0]->move();
objects[1]->move();
The first call to move will call the move method defined in the Car method. And the second one will call the move defined in Submarine. Because you may have a vector of Vehicule* but when you call the function and because it is virtual, you are calling the appropriate version of it. And by calling only one function you have different behaviours.
You may add as many derived class of Vehicule, you just have to adapt the move method.
You should search stackoverflow for polymorphism, there are far more detailed and accurate answers that the one I just wrote.
Sorry for the mistakes, I'm not a native-english speaker.
This following question is a bit hard for me to formulate, but please bear with me, and let me know if I can help in clearing anything up.
I am writing a general-purpose simulation for 3D shapes. I am using a base class:
class Shape{
public:
...
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
Now, since I don't know what shape the user will choose, I derive several classes from this. (e.g.: Sphere, Cube, Tetrahedron, etc.)
So far, everything is fine.
The main problem comes in the form that I have a Controller class, which launches and operates the simulation. As a private member, it should have a vector of multiple shapes (all of the same type. e.g.: 15 spheres, or 10 cubes, etc.)
class SimulationControl{
public:
void runsimulation();
private:
vector<Shape> all_shapes;
...
};
I wanted to simply initialize this private member with a non-default constructor.
Now, before I knew what I had done, Eclipse already told me that "The type 'Shape' must implement the inherited pure virtual method 'Shape::return_volume'"
I understand the error message and my mistake, of course, but I still don't understand how I can solve it.
What I would love to be able to do is to leave the type of vector undefined, and then simply create it via the constructor with the correct derived class at runtime, when I know which type of simulation the user chose.
Is is somehow possible to do that? Thanks
I'm not going to jump on the bandwagon and suggest using pointers in your container, whether smart or dumb. This is the perfect opportunity to use the PIMPL idiom.
The idea is that the class is simply a wrapper for the actual implementation, and calls a pointer to another object when a call is made to it. The pointer contained within the wrapper can be polymorphic so that it can implement the functions however it sees fit.
class Shape{
public:
Shape() { pImpl = NULL; }
Shape(const Shape& from) { pImpl = from.pImpl->clone(); }
~Shape() { delete pImpl; }
Shape& operator=(const Shape& from) { pImpl = from.pImpl->clone(); }
...
double return_volume() { return pImpl->return_volume(); }
private:
ShapeImpl * pImpl;
...
};
class ShapeImpl{
public:
...
virtual ShapeImpl* clone() const =0;
virtual double return_volume() =0;
private:
vector<double> coordinates;
...
};
Because the Shape class contains a pointer you'll need to implement the rule of three and create a destructor, copy constructor, and operator=. The defaults for the copies will certainly do the wrong thing - they'll only copy the pointer value without creating a new copy of the pimpl object to go with them. Since a vector copies elements around these functions are certain to get called.
Use (smart) pointers.
You cannot instantiate an abstract class, and even if you could, that would probably not be what you want, since you wouldn't be able to create aliases of those shapes.
You should change the definition of your SimulationControl class into something more similar to this (assuming shared ownership for your shapes here - if SimulationControl is the only owner of your shapes, rather use unique_ptr instead of shared_ptr):
#include <memory>
class SimulationControl {
public:
void runsimulation();
private:
std::vector<std::shared_ptr<Shape>> all_shapes;
...
};
Then, you could create instances of your shapes and add them to the all_shapes collection as follows (supposing MyShape is a concrete, default-constructible class derived from Shape):
std::shared_ptr<MyShape> pShape = std::make_shared<MyShape>();
pShape->set_vertices(...); // I guess the class will have a member function
// that allows setting the shape's vertices...
all_shapes.push_back(pShape);
You can only do polymorphism by pointer or reference. Try using vector<Shape*>.
Now that you are using pointers you'll have to manage the memory for them, but that is another set of questions. Try to use smart pointers if you can, or be very careful if you can't. If you are using C++11, std::vector<std::unique_ptr<Shape>> might fit the bill for you.
I am working on a C++ project, specifically implementing a shunting yard algorithm.
I have a function that creates a vector of shared_ptr's of type super class, but the classes that are being pushed into this vector are all base class shared_ptrs.
I then need to take this vector and pass it into another function and carry out different logic for each element of the vector in a for loop. The logic that I carry out, however, depends on which base class is present in each element of the vector.
So basically what I don't know is how to identify which type of base class is in each element of the vector. When I debug they are all coming out as type super-class.
So generally I'd like to do something like this:
if(vectorElement == baseClass)
{
//do some logic
}
Or if there is some different method of carrying this out which I'm missing I'd be interested in carrying that out.
There are many solutions to your problem, frankly is the almost most common problem in OOP.
The most obvious is the virtual function doing different things in different classes:
class SuperClass {
public:
virtual void doSomething(/*someArgsIfNeeded*/) {
// some base implementation, possible empty
// or just use pure virtual function here
}
};
class SubClass : public SuperClass {
public:
virtual void doSomething(/*someArgsIfNeeded*/) {
// some base implementation
}
};
Then use it as follows:
int SomeArgs;
std::vector<std::shared_ptr<SuperClass>> objects;
for (auto it = objects.begin(); it != objects.end(); ++i)
it->doSomething(/*someArgsIfNeeded*/);
Other more sophisticated solution is to use visitor pattern.
It is considered a bad practice to use casting (dynamic_cast), so always search for more OO solutions than casting, like these two I presented above.
Off the top of my head, a simple solution would be to have a function in the base class, that returns an int signifying which class it is. And in each of the derived classes, override this function to return different values. You could use that value to determine which class is being stored in the vector
Edit: And Generally class specific details are to be left in the class, which is the point of polymorphism. Try to do the derived class specific calculations as an overided member function within each class, and use that just to fetch the value forgoing the need for large for loops (for each new derived class) outside.
I am working on a game that has monsters and dragons. Dragons can do everything monsters can do except they can also breathe fire.
I have made a class of type 'monster' and a class that inherits from monster called 'dragon'.
I then have a class called 'monsters' which has as a private member vector which will contain dragon and monster elements.
In the main game loop I need to cycle through the vector and blow fire if the current element is a dragon, and do nothing if it is just a monster.
I have tried using typeid() but it always returns monster* whether the current element is a plain monster or a dragon.
Is there any way to do this or does it not make sense to even use inheritance in this case?
Would it make more sense for the dragon class to not inherit, and to instead stand by itself independent of monster?
Any advice is appreciated.
You could do something like this.
class Monster {};
class Dragon : public Monster
{
public:
void BlowFire() {}
}
std::vector<Monster*> monsters; // Collection of monsters
for(auto it = monsters.begin(); it != monsters.end(); ++it)
{
Dragon* pDragon = dynamic_cast<Dragon*>(*it); // Attempt to convert pointer
if(pDragon)
{
pDragon->BlowFire(); // If it is indeed a Dragon, blow fire.
}
}
But it sounds like you should arrange your classes a little better. Why don't you just have all your monster classes have an Attack method? This way you can override the methods for each different monster type.
class Monster
{
public:
virtual void Attack() {} // All monsters can attack
};
class Dragon : public Monster
{
public:
virtual void Attack() { // Do something special for a Dragon. }
};
Monster myMonster;
Dragon myDragon;
myMonster.Attack(); // Generic monster attack.
myDragon.Attack(); // Special super dragon fire attack!
There are two possible approaches: use a virtual function or use a dynamic_cast. If monster has a virtual function blow_fire() that does nothing, dragon can override it to do whatever is appropriate for a dragon. Then you just call it for all the monster objects, and the dragons will blow fire. Using dynamic_cast, the code would be something like this:
if (dragon *dragon_ptr = dynamic_cast<dragon*>(monster_ptr)) {
dragon_ptr->blow_fire();
}
That's generally viewed as a bad approach, because it doesn't grow naturally. If you added another type of monster that could blow fire you'd have to add another dynamic_cast. With a virtual function, the new type would just override the virtual function.
Not that this is the best way to do it, but just for your information, you were calling typeid on the pointer which doesn't work if you want the runtime type of the object. typeid does work at runtime when it needs to, but you need to dereference pointers to polymorphic types:
typeid(*monsterpointer)
And that will get the runtime type of *monsterpointer, be it a monster or dragon.
However, typeid is only for exact comparisons, so if you add another class called ImpairedDragon that inherits from Dragon, the typeid code will break and not work with them. So you should probably use dynamic_cast which works with inheritance, or even better, a virtual function if you can think of how to use one well.
If you've got monster pointers in your container, then public monster members are all you are able to access through those pointers in a type-safe way (from my recollection). You might try resorting to an interface-based design รก la COM so that you can query the monster base class for any extra features i.e. interfaces. I'd provide you with a sample but my lunchtime is now over.
How about putting an empty (no operation) virtual blowFire in the base class, and then overriding it with something in the derived class?
It would be even better to rename the method to specialAttack or a similar generic name, so you don't need to add similar methods for other kinds of Monsters.