I'm working on a game for an assignment and I've ran into an issue with function overriding in C++.
I have the following structure:
class GameEntity
{
public:
bool GameEntity::TakeHit(int dmg);
};
class Enemy : public GameEntity
{
bool Enemy::TakeHit(int dmg);
};
When from another class I create an instance of an Enemy, store it in a GameEntity vector, then call TakeHit() on it, it's calling the GameEntity version of it. I'm used to Java where this would call the other version, am I doing something obviously wrong here?
Other questions don't really cover this so I've created my own.
It's probably something pretty simple I'm guessing, so apologies for the trouble.
Make TakeHit a virtual member function.
// You don't need the scope specifier GameEntity::
// Make it pure virtual to force sub-classes to implement them.
virtual bool TakeHit(int dmg) = 0;
Store pointers to objects, preferably smart pointers, instead of objects. If you store just objects, you suffer from object slicing problem.
The function from GameEntity needs the virtual keyword.
Related
I have a class hierarchy with lots of shared member functions in a base class, and also a large number of unique member functions in two derived classes:
class Scene {
public:
void Display();
void CreateDefaultShapes();
void AddShape(Shape myShape);
// lots more shared member functions
}
Class AnimatedScene : public Scene {
public:
void SetupAnimation();
void ChangeAnimationSpeed(float x, float y);
// lots of member functions unique to animation
}
Class ControllableScene : public Scene {
public:
void ConfigureControls();
void MoveCamera(float x, float y, float z);
void Rotate(float x, float y, float z);
// lots of member functions unique to a controllable scene
}
Not surprisingly, this doesn't work:
Scene myScene;
myScene.SetupAnimation();
What is the correct solution to this problem? Should I make all of the derived member functions virtual and add them to the base? Should I use a cast when calling SetupAnimation()? Is there a more clever design that solves this problem?
Note: I receive myScene from elsewhere and can't simply declare it as AnimatedScene when I instantiate it.
Edit: I've added a couple more member functions to illustrate the point. A small handful of initialization functions definitely lend themselves to simply using virtual.
You can cast it, preferably using static_cast. The least preferable option. If you are casting things, it usually means your design needs more thought
If you have a particular function/class that needs one or the other, declare the input as the type you need, which more accurately communicates the requirements of the function or class
If the function needs to be generic, and those methods don't require any input, then you could define a virtual method in the parent class, say init, which in the derived classes call the correct methods to set up the instance.
I have a similar problem in my compiler project, where the AST (Abstract Syntax Tree) is constructed from the statements, so while(x != 0) { if (a == b) x = 0; } would construct a whileAST with a binaryExpr inside it, then a blockAST with the ifAST, and so on. Each of these have some common properties, and a lot of things that only apply when you actually do something specific to that part. Most of the time, that is solved by calling a generic (virtual) member function.
However, SOMETIMES you need to do very specific things. There are two ways to do that:
use dynamic_cast (or typeid + reinterpret_cast or static cast).
Set up dozens of virtual member functions, which mostly are completely useless (doesn't do anything or return an "can't do that" indication of some sort)
In my case, I choose the first one. It shouldn't be the common case, but sometimes it is indeed the right thing to do.
So in this case, you'd do something like:
AnimatedScene *animScene = dynamic_cast<AnimatedScene*>(&scene);
if (!animScene)
{
... do something else, since it's not an AnimatedScene ...
}
animScene->SetupAnimation();
I am not yet able to comment, which is what I really wanted to do, but I am also interested in figuring this out as well.
A few months ago I had a similar problem. What I can tell you is that you can use typeid operator to figure out what type the object is, like so:
int main()
{
scene* ptr = new AnimatedScene();
if (typeid(*ptr) == typeid(AnimatedScene))
{
cout<<"ptr is indeed a animatedScene"<<endl;
AnimatedScene* ptr2 = (AnimatedScene*)(ptr);
ptr2->SetupAnimation();
}
else
{
cout<<"not a animatedscene!!!"<<endl;
}
}
This works, you'll then be able to use ptr2 to access the animatedScene's unique members.
Notice the use of pointers, you can't use the objects directly, due to something called "object slicing" when playing with polymorphism: https://en.wikipedia.org/wiki/Object_slicing
Like you I have heard something about the use of typeid and thus, casting being a bad idea, but as to why, I cannot tell you. I am hoping to have a more experienced programmer explain it.
What I can tell you is that this works without problems in this simple example, you've avoided the problem of declaring meaningless virtual functions in the basetype.
Edit: It's amazing how often I forget to use google: Why is usage of the typeid keyword bad design?
If I understand mr Bolas correctly, typeid incentivizes bad coding practices. However, in your example you want to access a subtypes non-virtual function. As far as I know, there is no way of doing that without checking type at compiletime, ie typeid.
If such problem arises with your hierarchy that proves that hierarchy was too generalized. You might want to implement interfaces pattern, if class have certain functionality, it would inherit an interface that defines that functionality.
Proven that dogs are animals, do all animal but dogs fail to bark, or do only dogs bark?
The first approach lead to a class animal failing all the verses of the entire zoo, implemented one-by one in each animal. And in particular class dog will override just bark().
In this approach animal becomes a sort of "god object" (knows everything), requiring to be constantly updated every time something new is introduced, and requiring It's entire "universe" to be re-created (recompile everything) after it.
The second approach requires first to check the animal is a dog (via dynamic cast) and then ask it to bark. (or check for cat before asking a mieow)
The trade-off will probably consist in understanding how frequent is the possibility you have to check a bark out of its context (not knowing which animal are you deal with), how to report a fail, and what to do in case of such fail.
In other words, the key driver is not the bark, but the context around it inside your program.
//Are you trying to do something like this?
class Scene{
public:
virtual void Display()=0; //Pure virtual func
};
class AnimatedScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class AnimatedScene" <<std::endl;
}
};
class ControllableScene : public Scene{
public:
void Display(){
std::cout<<"function Display() inside class ControllableScene" <<std::endl;
}
};
int main(){
AnimatedScene as;
ControllableScene cs;
Scene *ex1 = &as;
Scene *ex2 = &cs;
ex1->Display();
ex2->Display();
return 0;
}
Now, I understand a good amount about abstract classes at this point, however, I was recently trying to use an abstract class to create a virtual function to receive messages and then another class that has an std::vector of smart pointers to this class, but then I got the error C2259. (yes, I did look it up here)
Side Note:
I also have recently been reading up a good amount on smart pointers since they are almost (if not always) mentioned in every question relating to pointers. So I decided to try and implement them for the first time, so my problem might actually be because of my improper use of smart pointers.
Anyways, here is the pure abstract class itself --
//Component.h
namespace rpg
{
class Component
{
public:
virtual void Receive(rpg::Message message) = 0;
Component();
virtual ~Component();
};
And here is the class that gets the error trying to use the pure abstract class.
//ContainerObject.h
#include <vector>
#include <memory>
#include "Component.h"
namespace rpg
{
class ContainerObject
{
private:
//Create short name for a vector of smart pointers to the pure abstract class
typedef std::vector<std::shared_ptr<rpg::Component>> ComponentList;
//Create array of Components (std::vector).
ComponentList myComponents;
public:
//Send message to all Components in array (std::vector)
void Send(rpg::Message message)
{
if(myComponents.size() > 0)
{
for(int i = 0; i < myComponents.size(); i++)
{
if(myComponents[i] != NULL)
{
myComponents[i]->Receive(message);
}
}
}
} // end of Send()
//Add new Component to array (std::vector)
void AddComponentToMessageList(rpg::Component& component)
{
myComponents.push_back(std::make_shared<rpg::Component>(component));
}
ContainerObject();
~ContainerObject();
};
} //namespace rpg
First off, I am trying to practice better code organization (which I am learning some here <-- also where I got most of this design) and I like the layout if I can keep it. I also read up some on pure abstract classes here and I saw near the bottom of the page that they still declare a list of pointers to objects of the pure abstract class so I am pretty sure I can use it this way, so why am I getting error C2295 and how can I fix it? Where might I be instantiating it and what causes it to be instantiated?
(I think the term instantiate is probably the part the really confuses me which is why I also asked what causes it, so if you could also include that in your answer it would be much appreciated. (And I did google its definition; I'm still confused))
void AddComponentToMessageList(std::shared_ptr<rpg::Component>& component)
{
myComponents.push_back(component);
}
Try it that way and create the object using std::make_shared before you call AddComponentToMessageList function. I have never tried to instantiate a class with a smart pointer using the copy constructor. From the first sight it looks like it should work, but you never know.
Another note. Prefer interfaces over abstract class. Meaning create an IComponent interface that will look like this:
class IComponent
{
public:
virtual void Receive(rpg::Message message) = 0;
virtual ~Component() { };
};
Then have your classes implement this interface. Obviously your vector needs to change, become a container of std::shared_ptr.
Now I also noticed that you cannot create an abstract class, regardless whether through "new", on the stack, or std::make_shared.
You are trying to instantiate Component when you call make_shared in this line:
myComponents.push_back(std::make_shared<rpg::Component>(component));
make_shared tries to execute new rpg::Component(component) which fails because Component is abstract.
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.
So this is probably a weird question, but I have a reasonably good reason for asking.
The gist of my question is, given an example with two levels of derivation on a class hierarchy:
Main Base Class:
class Animal
{
virtual void Draw() = 0;
};
Derived Class:
class Dog : public Animal
{
virtual void Draw()
{
// draw a generic dog icon or something...
}
};
Further Derivation:
class Corgi : public Dog
{
virtual void Draw()
{
// draw a corgi icon...
}
};
Now, I'd love to be able to, from within the Corgi class, permanently downcast the 'this' pointer to a Dog pointer and then pass it off somewhere else as an Animal. This other place will then be able to call the Draw function and get the Dog method, not the virtual Corgi method. I know this is strange, but again, I have a vaguely legitimate reason for wanting to do it.
I've tried all the different casting operators and haven't had any luck, but maybe there is a consistent way of pulling this off? In the past I've caused myself trouble by not properly using dynamic_cast which resulted in a similar state for a pointer. Perhaps this time I can use that to my advantage?
Edit:
Perhaps the above example doesn't illustrate clearly the what I'm trying to achieve, so I'll elaborate with my real goal.
I'm trying to achieve a shorthand for registering base class implementations that link into a scripting system I've been using for a while. The scripting system relies on a base class IScriptContext to facilitate access to real-code functions and member variable access. Internally base classes register their member function addresses and member variable addresses which are later dispatched/accessed through lookup tables. I'm in the process of adding proper support for class derivation hierarchies to the scripting system, and I figured being able to isolate the base class versions of these interfaces would help save time and make the whole process cleaner for me when it comes time to register available base classes with the script interpreter. There are other ways to achieve this, such as registering class specific function pointers for each required method for each available base class (e.g. this->Dog::CallFunction, this->Dog::SetMember, this->Dog::GetMember.) However, I figured using an interface would allow me to modify things a bit easier down the road if I ever needed to.
I hope all of that makes some kind of sense.
Thanks!
You have a Corgi object. You can:
Treat it as a Dog object everywhere by using the Dog:: qualifier to all calls (e.g. ptr->Dog::draw();). This loses you virtual dispatch, and is almost certainly not what you want from how your question reads.
Actually construct a new Dog object from your Corgi. Just do this with a normal static_cast as you'd convert any other type or let implicit conversion take over (e.g. Corgi c; Dog d(c);).
These are the options available to you. To want to retain a Corgi but automatically pretend everywhere that it's a Dog is neither reasonable nor legitimate, so the language does not provide for it.
Let me start off by saying your design looks faulty.
You can however explicitly say which function in a hierarchy you want to call:
Corgi* corgi = new Corgi;
corgi->Dog::draw();
This will call the draw method from Dog, not from Corgi. (I hope I understood correctly what you're asking).
Tomalak has already outlined two of the main choices available to you:
use qualified calls, or
construct a Dog as a Dog copy of your Corgi.
In addition to these, you can
use a simple wrapper
e.g.
class LooksLikeDog
: public Dog
{
private:
Dog* realObject_;
LooksLikeDog( LooksLikeDog const& ); // No such.
LooksLikeDog& operator=( LooksLikeDog const& ); // No such.
public:
LooksLikeDog( Dog& other )
: realObject_( &other )
{}
// Just for exposition: not implementing this does the same.
virtual void draw() override { Dog::draw(); }
// Example of other method that may need to be implemented:
virtual void bark() override { realObject_->bark(); }
};
But the best solution is most probably to fix your design. ;-)
Implement Corgi draw function and call your parent's implementation:
virtual void Corgi::Draw()
{
Dog::draw();
}
I'm a fairly experienced programmer, but I'm still relatively new to OOP architecture and design in c++.
Most of my experience is with C# and Java. I recently endeavored to code up a simple game engine in c++.
I used SDL for the graphics. In this post, I would like to discuss my architecture and to get some feedback
on it. Particularly, I've run into a design issue that I would like some help with. So, here goes:
In my main function, I initialize all of the SDL stuff for drawing to the screen, etc.
Then I instantiate all of the objects that I intend to use: floor, wall, player, etc.
Next I start the main loop. This loop executes each object's movement, collision detection and collision handling functions, and redraws them.
The main loop runs until the application is quit, drawing one frame each iteration.
My problem is this:
I tried to do a kind of interface-style design. It involves a series of
abstract base classes that allow each object to implement a behavior. For example, if I want an object to be movable,
it would have to inherit from the movable base class which contains a virtual function called move() and some position
coordinates. If I wanted it to be collidable, the object would inherit from the collidable abstract class, which
contains the virtual functions checkCollision() and handleCollision() as well as a hitbox member variable. An object
like the player inherits from both of these base classes as well as several others.
This works well enough as long as I'm doing everything by hand in the main loop. I can just say:
player.move();
player.checkCollision();
player.handleCollision();
player.draw().
and it's fine. But I would like to
be able to have a vector or array of generic objects in the main loop and do something like this:
for each object in vector
if object is of type movable
object.move();
if object is of type collidable
object.checkCollision();
I thought that I could accomplish this with dynamic casting, but I really haven't been able to come up with anything.
I've tried storing them as void pointers, but that doesn't work the way I want it to. I've been reading about this
gameobject-component architecture for video games that I might try, but I'd really like to salvage what I've already
written. I figure this is a good learning opportunity. If anybody has any ideas I'd really appreciate it. How does my architecture compare to other simple game engine designs? does my interface architecture make sense or is it totally wonky?
If you work in C++, try SFML, it's faster than SDL, and if you know OpenGL, you can use it too.
For your problem:
class Entity {
//constructor and other stuff
void virtual exec() =0; ///<= pure virtual method
};
class Movable : Entity {
void move(); //do somthing
void exec() {move();};
};
class Collidable : Entity {
void col(); //do your job
void exec(){col();};
};
std::vector<Entity*> e_v;
///push some instance
for (Entity* e : e_v)
e->exec();
What about using the template method pattern and non-abstract empty virtual functions in the base class?
class Entity
{
void update()
{
move();
checkCollision();
}
virtual void move() {}
virtual void checkCollision() {}
};
class Movable : public virtual Entity
{
virtual void move() {} // Stuff
};
class Collidable : public virtual Entity
{
virtual void checkCollision() {} // Stuff
};