consider this base class:
struct drawable
{
virtual void draw(sf::RenderWindow &window) const = 0;
};
and this derived class:
struct rectangle : drawable
{
rectangle(sf::Vector2f pos, sf::Vector2f size);
void draw(sf::RenderWindow &window) const;
sf::RectangleShape body;
};
I have similar derived classes for other shapes like circle, line and triangle. I use this function to return shapes based on a string of text I get from a file:
drawable * string_to_object(std::string name)
{
if (name == "RECTANGLE")
{
return new rectangle(sf::Vector2f(20,20), sf::Vector2f(5,5));
}
else if (name == "BALL")
{
return new ball(sf::Vector2f(10,10), 5, sf::Vector2f(0,0));
}
else if (name == "LINE")
{
return new line(sf::Vector2f(30,30), 10, 5);
}
}
Now in my main I have variables like this to test if it works:
auto game_object = string_to_object("BALL");
Now the problem is I need to perform actions/checks on the shape's body, which is a member of the derived class that I cannot access from the drawable pointer variables. It's also a problem that the type of the body is not set, it can be a RectangleShape, CircleShape etc so a getBody() function would need a variable return type. How would I go about getting access to the body in a generic way? I've tried templates but I realized that won't work since it's a runtime problem.
If I understand your question correctly, there are multiple ways how to solve this issue.
Re-think your architecture. You could introduce other virtual functions to drawable that every subclass implements. In these functions you'd implement all the checks/actions you need. Since they are implemented in the base class, they have access to the shape's body and since it is a virtual function of the base you can call these functions from the outside.
Since your drawable object has a virtual function, you could use RTTI to check the type at runtime and perform a dynamic_cast
See: https://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI
I'd prefer the first option whenever you can.
It sounds like you're having trouble deciding what functionality is generic to all drawable objects, and what is specific to rectangle, ball and so on. Attributes and methods that apply to all drawable objects can be declared within drawable, but anything that only applies to a particular kind of drawable (like the width and height of rectangle vs. the radius of a ball) go in the derived classes.
In your example, each of the derived classes must implement the draw method if you want to instantiate them (because it is declared pure virtual in the base drawable class). Each of these specific derived implementations can access the specific attributes of the derived class. So the rectangle::draw method can access the width and height, while the ball::draw method can access the radius.
Then, when you have a collection of pointers to drawable objects (which are really instances of the derived classes) you can simply call the draw method for each of them.
Sorry if this seems overly simplistic - I hope it's clear.
Related
I'm trying to inherit from two base classes in C++, that have same named functions. I want an object of the class to 'belong' to the particular base class, is it possible to do so?
I have tried virtual base class (does not suit my particular case) and also tried using scope resolution operator with failure.
I want to do this just by using a single class if it's possible.
I have provide the code;
#include <SFML\Graphics.hpp>
class entity :public sf::CircleShape, public sf::RectangleShape {
public:
entity(int radius = 0) { setRadius(radius); }
entity(sf::Vector2f size) { setSize(size); }
float xspeed =0, yspeed =0;
};
entity ball(6);
entity block(10, 10);
window.draw(block); // ambiguity error as both have base class sf::drawable
window.draw(ball); // and draw function accepts sf::drawable
The problem is that I want "ball" just to inherit from sf::CircleShape and not from sf::RectangleShape.
I expected using scope resolution operator would refer to the circleshape class or I might just be using it wrong.
Edit: The problem I'm trying to solve is that I want to draw "ball" and a rectangular block on to the window, and when I try to do that I'm presented with an ambiguity error as they both are drawable (i.e. both sf::RectangleShape and sf::CircleShape inherit from sf::drawable)
Edit(2): The inheritence diagram
So the function window.draw(); accepts any object of sf::drawable as a parameter. But as I inherit both circleshape and rectangle shape to entity I get an ambiguity error saying base class is ambiguous.
I know this is diamond of death situation however using virtual base classes is not possible as they are part of the SFML library and I do not want to modify them
Problem analysis
class entity :public sf::CircleShape, public sf::RectangleShape
This declaration says that every entity is simultaneously a CircleShape and a RectangleShape. This does not seem to be what you want. You seem to want an entity that can be either a circle or a rectangle. So this inheritance is not the right strategy.
Given that you are adding horizontal and vertical speeds, it seems like you are trying to add a basic animation to elements that can be drawn. Animation is an abstract concept that builds upon drawing (an animation must be drawn, but not all drawings must be animated). Specific moving shapes would build on top of the animation, so your ideal inheritance would be more like the following:
circle -> entity -> drawable
However, there are a few drawbacks. One drawback is that this forces all circles to be animated entities, when some circles might simply be drawn in one spot. Plus, the circle and drawable classes are from a library, so you cannot mess with that particular inheritance scheme.
I can think of two reasonable alternatives off the top of my head. (By the way, "entity" is not a great name for your class, but I'll stick with it for consistency. You should come up with a more descriptive name for the class. It'll be good practice, as naming things is sometimes one of the hardest parts of writing code. :) )
Entity as a base class
You could define entity as a base class, then define a new class for each shape.
--> sf::CircleShape --> sf::Drawable
/
MyCircle --<
\
--> entity
This can work, but it is not great if entity needs to invoke functions defined in Drawable. Not impossible: a side-cast can make it possible to invoke Drawable's functions. It's just that you then have to account for the case where the side-cast fails, as the compiler cannot catch that.
Shapes as members
What I would probably do is give up inheritance altogether. Instead of trying to say that your entity is a circle (inheritance), I would go with the approach that your entity has a circle (membership). One benefit of this approach is that it is not hard to extend this to saying that your entity has multiple shapes, all moving at the same speed. I will, though, stick to a single shape for now.
The difficulty with this approach is that you don't know what shape the entity should have -- should it have a circle or a rectangle? Fortunately, this is the sort of thing polymorphism deals with nicely.
class entity {
std::unique_ptr<sf::Drawable> shape; // <-- Polymorphism to the rescue!
float xspeed = 0.0, yspeed = 0.0;
public:
// Construct a circle.
entity(int radius = 0) : shape(std::make_unique<sf::CircleShape>(radius)) {}
// Construct a rectangle.
entity(sf::Vector2f size) : shape(std::make_unique<sf::RectangleShape>(size)) {}
// Something will go here to support drawing.
};
To support drawing, there are (at least) two options. If it is appropriate to have an entity be a drop-in replacement for a Drawable, it might be reasonable to define an implicit conversion.
operator const sf::Drawable &() const { return *shape; }
If an implicit conversion is not desirable, marking it explicit is an option.
If the only time you need to use an entity as a Drawable is when you call window.draw(), you might want to instead give entity a draw method that takes window as a parameter.
void draw(sf::RenderTarget & target, sf::RenderStates states) const
{ target.draw(*shape, states); }
This makes the Drawable available to RenderTarget::draw() while keeping it out of sight (clutter reduction) at other times.
instead of using inheritance :
simply use direct association :
in your entity class, you want to have RectangleShape and CircleShape , so instead of making the entity class a CircleShape and a RectangeShape at the same time, it's better to consider your entity made of a CircleShape and a RectangleShape .this way you can in your entity class instantiate a RectangeShape and a CircleShape means 'entity' has a Rectangle and a CircleShape
it's the correct way to do it
The title sucks I know.
The problem here is that I have a 2D and 3D shape class that inherits from a shape class
class Shape {
public:
virtual double area() = 0;//Calculates the area of some kind of shape
~Shape() { delete this; }
};
class Shape2D :public Shape {
public:
virtual double perimeter() = 0;//Calculates the perimeter of some kind of 2D-shape
~Shape2D() {};
};
class Shape3D :public Shape {
public:
virtual double volume() = 0;//Calculates the volume of some kind of 3D-shape, area function will return surface area
~Shape3D() {};
};
It is decided that all shapes will default have an area. In 2D shapes, it'll have a virtual perimeter method and also and area from Shape. In 3D shapes, it'll have a volume and the vitual area method will be treated as a surface area.
The way that I've gone about is that within a menu that can choose 2d or 3d shapes: within the 2d menu, I initiate:
Shape2D * s = nullptr;
and within the 3d menu, I'll initiate:
Shape3D * s = nullptr;
and then to display whatever information, I use the methods:
void displayShape2D(Shape2D *)
and
void displayShape3D(Shape3D *)
However, the way that I want to go about it is to declare:
Shape *s = nullputr;
at the beginning of main and then at whatever shape the user chooses, I can just set:
s= new Triangle()
or
s = new cube();
The initialization works but when I try to make a display method, that's where I run into a problem. I want to be able to do:
displayShape(Shape *s)
When given a 2d shape and within the method I try:
cout <<s->perimeter();
It'll say that the perimeter member is not within the shape class.
The problem then is trying to be able to determine if a the shape is 2d or 3d and then display the area and perimeter for 2d or surface area and volume for 3d. Is this possible or is creating the shape types within the dedicated menu and then having dedicated display methods the only way out?
While the other answer "works" it's not the approach I'd take here. Basically you want to execute different code depending on the dynamic type of an instance: that's what virtual functions are for.
So just add a (possibly pure) virtual display member function to your Shape class and implement it accordingly in the deriving classes.
Contrary to the dynamic_cast approach this doesn't break when you add more deriving classes or classes that are derived even "further".
Finally:
~Shape() {
delete this;
}
This destructor is the C++ equivalent of taking a shot gun and shooting yourself into the face. With a stack or static allocated instance this will lead to a bogus free (as the instance was never allocated from the heap), with a heap allocated it will lead to a double free (since the destructor is called just before freeing the occupied memory of the instance).
What you must do in your case is make the destructor virtual. Otherwise, having only Shape * it's impossible to correctly destruct the pointed to instance!
This is how such "display" functionality is "commonly" implemented, at least AFAIK:
struct Shape {
virtual void write_to(ostream &) const = 0;
virtual ~Shape() {}
};
struct Shape2D : public Shape {
void write_to(ostream & stream) const {
stream << "<2D, whooo>";
}
};
struct Shape3D : public Shape {
void write_to(ostream & stream) const {
stream << "<I got depth, man!>";
}
};
ostream & operator<<(ostream & stream, Shape const & shape) {
shape.write_to(stream);
return stream;
}
Now one can write any Shape (when using a pointer, dereference it) to any ostream, C++ "style":
std::unique_ptr<Shape> awesomeShape = std::make_unique<Shape2D>();
std::cout << "Awesome is: " << *awesomeShape << std::endl;
Here, first operator<<(ostream &, Shape &) is called (which it would for any Shape-like thing) which calls the virtual member function write_to, which is implemented in different ways for each derived class (though there could be a generic implementation in Shape, too!). See also this.
A possible issue with the dynamic_cast approach occurs when you deepen your hierarchy:
struct ThickShape2D : public Shape2D {
// whatever
};
An instance with dynamic type ThickShape2D can also be dynamic_cast to a Shape2D, thus you'd need to keep an careful eye on the order of these if clauses.
But, to quote Jarra McIntyre:
I think it is worth mentioning that the design trade offs between using virtual functions and the above approach (and any other approaches) are complex. The above approach allows runtime dispatch on multiple types, and simplifies things such as (going back to the above) having multiple draw functions.
I completely second that. There's the visitor pattern (and also it's acyclic variant), probably the command pattern and a a lot of other things one can start looking at if one needs further information. For an extensive discussion about the uses of (raw) RTTI see this question and its answers.
As a final note: I don't know exactly what you're trying to model, but consider that inheritance is most often not the best approach available. When possible, prefer composition over inheritance. Entity component systems are a nice thing to look at.
(The above paragraph contains 6 links, just so that noone misses something.)
What you want to do is runtime type dispatch. One method is to use RTTI. This allows you to do something like this:
Shape *s = ...;
if(Shape3D *s3d = dynamic_cast<Shape3D*>(s)) {
// s3d is now a pointer to a 3d shape
} else if(Shape2D *s2d = dynamic_cast<Shape2D*>(s)) {
// s2d is now a pointer to a 2d shape
} else {
// s is neither a Shape2D or Shape3D
}
This works because dynamic_cast(s) evaluates to a nullptr if s cannot be cast to Type*. Therefore the if statement condition only evaluates to true if s can be cast to the specified type.
I am creating an application that allows a user to define dimensions for different shapes and returns the area to the user using the dimensions they specified.
My base class is Shape. Derived classes are Triangle, Circle, Square and Rectangle.
I have created an array of Shape in the hope of creating and storing instances of any of the derived classes in the array during runtime.
Shape** shape = new Shape*[TOTAL_SHAPES];
shape[i] = new Circle(radius);
I have managed this, however I am unable to access the instantiated classes methods. Sorry if this is a stupid question I am fairly new to C++.
Let's assume your types had the following definition
class Shape {
public:
void Method1() { ... }
};
class Circle : public Shape {
void Method2() { ... }
}
With this definition you could access methods on Shape by doing the following
shape[i]->Method1();
In this context though it wouldn't be possible to access Method2 though because the compiler only knows about Shape, not Circle.
shape[i]->Method2(); // Error!
You have three options:
Make Shape an abstract base class and call virtual methods that are members of Shape
Use static_cast to cast from a Shape* to a Circle*, and call methods through that.
Use dynamic_cast to cast from a Shape* to a Circle*, and call methods through that.
The first option is likely best in many cases. Among other reasons, you almost surely need to have a virtual destructor (which can be a by-product of making Shape an ABC), and you may prefer to not have to know what type of object is being pointed to, rather you'd like to simply call methods on whatever it may be. If you can use this idiom, use it.
The second option is dangerous. You must absolutely know that the object being pointed to is a Circle (or whatever) in order to use static_cast, else you will get Undefined Behavior.
The third option is only possible if your class is polymorphic, which means Shape must have at least one virtual method. You surely should have a virtual destructor, and this would serve that purpose.
How about that:
shape[i]->aMethod();
For starters, I highly recommend using a smart pointer wrapper instead of using raw pointers (especially if you are new to the language).
std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);
That will define a vector with an initial size of TOTAL_SHAPES.
To the root of your problem, any method you wish to call using a Shape* must be valid for Shape, or you must do a risky downcast to the appropriate type. For example:
class Shape
{
public:
// constructors and other methods go here
virtual ~Shape() { } // virtual destructor
virtual void Draw() { } // virtual function to be used by derived classes
};
class Circle
{
public:
// ...
virtual ~Circle() { }
virtual void Draw() { } // override the virtual function
};
Then, in your application code,
std::vector<std::shared_ptr<Shape>> shapes(TOTAL_SHAPES);
shapes[0] = std::make_shared(new Circle);
shapes[0]->Draw(); // calls Circle::Draw
Note that depending on your usage, std::unique_ptr may replace std::shared_ptr.
I am implementing a visual tree in SFML. SFML contains two important drawing classes: sf::Drawable and sf::Transformable. It would be nice if these were bundled up together, but they are not. Many objects inherit from both, i.e.:
class SFML_GRAPHICS_API Text : public Drawable, public Transformable
class SFML_GRAPHICS_API Sprite : public Drawable, public Transformable
class SFML_GRAPHICS_API Shape : public Drawable, public Transformable
For my visual tree, I have a SceneNode class that inherits from Drawable and Transformable, and a draw function will call a private onDraw itself, and then its children. However, many SFML native classes, such as sf::Text, have a draw function that is private. So, I cannot create a class like
class Text: public sf::Text, public SceneNode
and then put it into the visual tree. For these native classes, I don't need them to have draw children anyway, I just want to be able to add them to the visual tree as leaf nodes. The crux of the problem is that each member of the visual tree needs to inherit from sf::Drawable and sf::Tranformable. I need to be able to define a type that inherits from both of these. If I define the dummy class
class LeafNode: public sf::Drawable, public sf::Tranformable { }
which appears to define the type I want. Then, SceneNode will contain std::vector<LeafNode*> m_children. When drawing these children, I will do a dynamic cast on each item to see if it is a SceneNode, and then call a draw function so the SceneNode draws its children.
However the following code does not compile due to type incompatibility:
LeafNode * node = new sf::Text("PLAY", font, 20);
Ideally, I want to define something like
std::vector<sf::Drawable, sf::Transformable*> m_children
Where that made-up syntax means that each element must derive from both sf::Drawable and sf::Transformable. Is this possible?
However, many SFML native classes, such as sf::Text, have a draw function that is private
That's not quite true. Since the sf::Drawable::draw function is protected, so is the draw method of sf::Text. It's one of the complex rules of C++.
So, I cannot create a class like
class Text: public sf::Text, public SceneNode
If you did you would have two sf::Drawable and sf::Transformable base classes in your hierarchy, one from sf::Text and one from SceneNode. That wouldn't be good.
When drawing these children, I will do a dynamic cast on each item to see if it is a SceneNode, and then call a draw function so the SceneNode draws its children.
I would not recommend such design. Using dynamic_cast is usually a sign your software design is not so great. (I don't want to digress too much on this topic, google about that topic.)
But let's answer your fundamental question:
Where that made-up syntax means that each element must derive from both sf::Drawable and sf::Transformable. Is this possible?
No. But you can do simpler things anyway.
Instead of having Text inheriting from both sf::Text and SceneNode, define you class as a wrapper. It can be as simple as:
class Text : public SceneNode {
sf::Text m_text;
public:
sf::Text& get() { return m_text; }
// Override SceneNode drawing method:
virtual void onDraw(RenderTarget& target) const
// Draw m_text:
target.draw(m_text);
}
};
There is two flaws with this quick wrapper, though. a) It doesn't use the transformable part of the SceneNode. b) Since the encapsulation is broken with get() there are two transformable modifiable by the user: the one from SceneNode and the one of sf::Text.
For a), the fix should be straightforward when you have fixed b). To fix b), you have to make the wrapper a little bit more complex: instead of having this ugly get(), write methods to set the properties of the underlying sf::Text that are not linked to sf::Transformable, e.g. setColor.
Without knowing anything about SMFL (which may provide better solutions) I think you can implement this vector. You only need to define your own pointer wrapper, which only accepts pointers to objects which inherits from more than one type:
template <class T1, class T2>
struct special_pointer_wrapper
{
T1* t1;
T2* t2;
template<class T>
special_pointer_wrapper(T* p)
: t1(dynamic_cast<T1*>(p))
, t2(dynamic_cast<T2*>(p))
{
if ((p1==0) || (p2==0))
throw "Error";
}
getT1 T1* () const { return t1; }
getT2 T2* () const { return t2; }
};
This class takes any pointer and ensures its pointed to type is derived from T1 and T2 (even if they seem to be totally unrelated). If its not a derived object it throws. With functions getT1() and getT2() it gives you access to pointers to both base classes.
Please note the construction may be slow due dynamic_cast but extraction of the types is O(1).
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can someone explain C++ Virtual Methods?
I have a question regarding to the C++ virtual functions.
Why and when do we use virtual functions? Can anyone give me a real time implementation or use of virtual functions?
You use virtual functions when you want to override a certain behavior (read method) for your derived class rather than the one implemented for the base class and you want to do so at run-time through a pointer to the base class.
The classic example is when you have a base class called Shape and concrete shapes (classes) that derive from it. Each concrete class overrides (implements a virtual method) called Draw().
The class hierarchy is as follows:
The following snippet shows the usage of the example; it creates an array of Shape class pointers wherein each points to a distinct derived class object. At run-time, invoking the Draw() method results in the calling of the method overridden by that derived class and the particular Shape is drawn (or rendered).
Shape *basep[] = { &line_obj, &tri_obj,
&rect_obj, &cir_obj};
for (i = 0; i < NO_PICTURES; i++)
basep[i] -> Draw ();
The above program just uses the pointer to the base class to store addresses of the derived class objects. This provides a loose coupling because the program does not have to change drastically if a new concrete derived class of shape is added anytime. The reason is that there are minimal code segments that actually use (depend) on the concrete Shape type.
The above is a good example of the Open Closed Principle of the famous SOLID design principles.
You use virtual functions when you need handle different objects in the same way. It`s called polymorphism. Let's imagine you have some base class - something like classical Shape:
class Shape
{
public:
virtual void draw() = 0;
virtual ~Shape() {}
};
class Rectange: public Shape
{
public:
void draw() { // draw rectangle here }
};
class Circle: public Shape
{
public:
void draw() { // draw circle here }
};
Now you can have vector of different shapes:
vector<Shape*> shapes;
shapes.push_back(new Rectangle());
shapes.push_back(new Circle());
And you can draw all shapes like this:
for(vector<Shape*>::iterator i = shapes.begin(); i != shapes.end(); i++)
{
(*i)->draw();
}
In this way you are drawing different shapes with one virtual method - draw(). Proper version of method is selected based on run time information about type of object behind pointer.
Notice
When you use virtual functions you can declare them as pure virtual(like in class Shape, just place " = 0" after method proto). In this case you won't be able to create instance of object with pure virtual function and it will be called Abstract class.
Also notice "virtual" before destructor. In case when you are planning work with objects through pointers to their base classes you should declare destructor virtual, so when you call "delete" for base class pointer, all chain of destructors will be called and there won't be memory leaks.
Think of animals class, and derived from it are cat, dog and cow. Animal class has a
virtual void SaySomething()
{
cout << "Something";
}
function.
Animal *a;
a = new Dog();
a->SaySomething();
Instead of printing "Something", dog should say "Bark", cat should say "Meow". In this example you see that a is a Dog, but there are some times that you have an animal pointer and don't know which animal it is. You don't want to know which animal it is, you just want the animal to say something. So you just call virtual function and cats will say "meow" and dogs will say "bark".
Of course, SaySomething function should have been pure virtual to avoid possible errors.
You would use a virtual function to implement "polymorphism", in particular where you have an object, don't know what the actual underlying type is, but know what operation you want to perform on it, and the implementation of this (how it does it) differs dependent on what type you actually have.
Essentially what is commonly called the "Liskov Substitution Principle" named after Barbara Liskov who spoke about this around 1983.
Where you need to use dynamic runtime decisions where, at the point the code invoking the function is called, you do not know what types may pass through it, either now or in the future, this is a good model to use.
It isn't the only way though. There are all sorts of "callbacks" that can take a "blob" of data and you might have tables of callbacks dependent on a header block in the data that comes in, e.g. a message processor. For this there is no need to use a virtual function, in fact what you would probably use is sort-of how a v-table is implemented only with one entry (e.g. a class with just one virtual function).