To polymorph or to incapsulate, this is the question! (C++) - c++

I need to store a polymorphic object (let's say Polygon) inside another object (let's say Simulation). At the same time I want to keep encapsulation of Simulation.
class Polygon {
public:
virtual double area() { return 0; }
};
class Square : public Polygon {
public:
Square(double edge) : edge_(edge) {}
virtual double area() { return edge_*edge_; }
private:
double edge_;
};
class Simulation {
public:
Simulation(Polygon& polygon) { polygon_ = &polygon; }
Polygon* polygon() { return polygon_; }
private:
Polygon* polygon_;
};
int main (int argc, const char * argv[]) {
Square square(2.0);
Simulation sim(square);
std::cout<<sim.polygon()->area()<<"\n";
return 0;
}
This works perfectly fine! However, it violates encapsulation of Simulation, in fact, if from the main I go and change square it will also change inside Simulation.
I was thinking of modifying the constructor of Simulation using the copy constructor as:
Simulation(Polygon& polygon) { polygon_ = new Polygon(polygon); }
but this will mean that I don't have polymorphism...
There is obviously something I am missing here... CHEERS!

Add a clone function to Polygon (and a virtual destructor!). It is a good idea to ensure that Polygon is abstract so make sure at least one function is pure virtual.
Your Simulation class will require a copy constructor, destructor and assignment operator.
Note that the Square clone function can return a Square* even though the super class returns a Polygon* because it is covariant. Some older compilers may not support this, in which case return a Polygon*.
class Polygon {
public:
virtual ~Polygon() = 0;
virtual Polygon* clone() const = 0;
virtual double area() { return 0; }
};
inline Polygon::~Polygon() {}
class Square : public Polygon {
public:
Square(double edge) : edge_(edge) {}
virtual Square* clone() const { return new Square(*this); }
virtual double area() { return edge_*edge_; }
private:
double edge_;
};
class Simulation {
public:
Simulation(Polygon const& polygon)
: polygon_(polygon.clone())
{}
Simulation(Simulation const& rhs)
: polygon_(rhs.polygon_->clone())
{}
Simulation& operator=(Simulation const& rhs)
{
if (this != &rhs) {
delete polygon_;
polygon_ = rhs.polygon_->clone();
}
return *this;
}
~Simulation() {
delete polygon_;
}
Polygon* polygon() { return polygon_; }
private:
Polygon* polygon_;
};

If Simulation contains Polygon then it means that it is meant to do something with it. If you need to access the polygon directly from the 'outside', you have either missed the design somewhere, or if not, you can use observer pattern and have polygon notify the simulation if something about it changes.
So, either:
outside -> polygon -> callback -> simulation
or
outside -> simulation -> polygon

So you want to make sure that there's no way for outside code to alter the inner polygon of simulation, but yet allow any subclass to be used inside it? I.e. make sure that there are no references outside of simulation to the object passed by ref in the c'tor?
You could think of an abstract copy method to accomplish that: (don't forget to delete in simulation destructor)
class Polygon {
public:
virtual Polygon *copy() = 0;
//..
};
class Square : public Polygon {
public:
virtual Polygon *copy() { return new Square(_edge); }
//...
}
class Simulation {
public:
Simulation(const Polygon &p) : poly(p.copy()) {}
};

If you want to copy a polymorphic object, this can be done with a clone method.
class Polygon
{
...
virtual Polygon* clone() const = 0;
};
class Square: public Polygon
{
...
virtual Square* clone() const { return new Square(*this); }
};
However, in the example it seems a bit pointless that the Simulation neither does anything with the polygon itself nor do you want to hand it out for other code to use.

That's just how C++ works. If you write a wrapper for an object (PIMPL) you have to implement its full interface. The functions going to be very small just passing the calls to the actual implementation but you have to write them. Then you can alter the behaviour, add logging, or whatever you need...

You just need to decide if the polygon is inside or outside of simulation. If it's supposed to be outside of it, then you have reference constructor parameter . If it's inside, you'll need the following code:
class Simulation {
public:
Simulation() : poly(2.0) { }
Polygon *polygon() { return &poly; }
private:
Square poly;
};
Now, the polymorphism aspect you can easily do like this:
class Simulation {
public:
Simulation() : poly(2.0), poly2(3.0) { }
Polygon *polygon(int i)
{
switch(i) {
case 0: return &poly;
case 1: return &poly2;
}
return 0;
}
private:
Square poly;
Cylinder poly2;
};
And once you get tired to adding new data members, here's another trick which will fix some cases:
class Simulation {
public:
Simulation() : poly(2.0) { }
Polygon *polygon(float x)
{
poly.edge_ = x;
return &poly;
}
private:
Square poly;
};
Edit: Note that the order of classes in header file needs to be carefully considered.

Related

How would you hand a member of a class implementing an interface to another class using the interface?

I was just experimenting with interfaces and wrapping classes and I have come across a roadblock. I am wrapping an SFML::RenderWindow in a class that implements a draw() function. For example:
struct ISprite {
....
functions for sprites...
....
}
class SFML_Sprite : public ISprite
{
public:
....
functions implementing stuff for sprites
....
private:
sf::Sprite mSprite;
}
struct IWindow {
...
virtual void draw(const ISprite& sprite) = 0;
...
}
class SFML_Window : public IWindow
{
public:
...
void draw(const ISprite& sprite)
{
//This is where the problem is. Is there a way for me to get to
//mSprite?
mWin.draw(sprite.mSprite);
}
private:
sf::RenderWindow mWin;
}
In other words, is there a way for me to pass the underlying stuff around? A pattern I am missing? I am basically trying to hide the windows and sprite implementations. Eventually, I would like to try 'swapping' implementations and go a little lower level, but if I can't figure this out, I am no where near ready to try that.
Thanks!
Why don't you want to do the cast? It's safe and well defined in this context:
class ISprite {
};
class SFML_Sprite : public ISprite
{
};
class IWindow {
public:
virtual void draw(const ISprite& sprite) = 0;
};
class SFML_Window : public IWindow
{
public:
void draw(const ISprite& _sprite)
{
auto sprite = static_cast<const SFML_Sprite&>(_sprite);
}
};
int main() {
SFML_Window i;
IWindow &a = i;
SFML_Sprite x;
ISprite &y = x;
a.draw(y);
return 0;
}
You can use dynamic_cast if you want to pay for a runtime check to ensure you're really getting the right type, but you always should be as you're not going to be mixing two different graphics backends in the same code.

Double dispatch and factory pattern

I've got the following code currently (not working):
#include <iostream>
#include <vector>
class Circle;
class Rectangle;
class Shape {
private:
Shape() {};
public:
virtual ~Shape() {};
friend class Circle;
friend class Rectangle;
};
class Creator {
public:
virtual ~Creator() {};
virtual Shape* create() = 0;
virtual bool equals(Shape& s) { return false; };
};
class Circle : public Shape {
private:
Circle() : Shape() {};
public:
class CircleCreator : public Creator {
public:
virtual Shape* create() { return new Circle(); };
virtual bool equals(Shape& other_shape) { return false; };
};
};
class Rectangle : public Shape {
private:
Rectangle() : Shape() {};
public:
class RectangleCreator : public Creator {
public:
virtual Shape* create() { return new Rectangle(); };
virtual bool equals(Shape& other_shape) { return false; };
};
};
int main() {
/* First step, build the list */
std::vector<Shape*> shapeList;
std::vector<Shape*>::iterator it;
Rectangle::RectangleCreator rc;
Circle::CircleCreator cc;
Shape* s = cc.create();
Shape* s1 = rc.create();
shapeList.push_back(s);
shapeList.push_back(s1);
/* Second step: check if we've got a shape starting from a creator */
for (it = shapeList.begin(); it != shapeList.end(); ++it) {
if (rc.equals(**it)) {
std::cout << "same shape" << std::endl;
}
}
return 0;
}
My goal is to use a factory pattern and avoid the creation of a new object if in a list I've got already that object. I tried to use a double dispatch pattern but it isn't easy to apply in this case. How can I do?
Edit: Since the code is used in a "critical" path, I want to avoid RTTI like dynamic_cast and so on.
Maybe something like this could do it using member variables
#include <iostream>
#include <vector>
enum
{
CIRCLE,
RECTANGLE
};
class Circle;
class Rectangle;
class Shape {
private:
Shape() {};
public:
unsigned shapeType;
virtual ~Shape() {};
friend class Circle;
friend class Rectangle;
};
class Creator {
public:
unsigned shapeType;
virtual ~Creator() {};
virtual Shape* create() = 0;
bool equals(Shape& s) { return (this->shapeType == s.shapeType); };
};
class Circle : public Shape {
private:
Circle() : Shape() {shapeType=CIRCLE;};
public:
class CircleCreator : public Creator {
public:
CircleCreator() {shapeType=CIRCLE;};
virtual Shape* create() { return new Circle(); };
};
};
class Rectangle : public Shape {
private:
Rectangle() : Shape() {shapeType=RECTANGLE;};
public:
class RectangleCreator : public Creator {
public:
RectangleCreator() {shapeType=RECTANGLE;};
virtual Shape* create() { return new Rectangle(); };
};
};
int main() {
/* First step, build the list */
std::vector<Shape*> shapeList;
std::vector<Shape*>::iterator it;
Rectangle::RectangleCreator rc;
Circle::CircleCreator cc;
Shape* s = cc.create();
Shape* s1 = rc.create();
shapeList.push_back(s);
shapeList.push_back(s1);
/* Second step: check if we've got a shape starting from a creator */
for (it = shapeList.begin(); it != shapeList.end(); ++it) {
if (rc.equals(**it)) {
std::cout << "same shape" << std::endl;
}
}
return 0;
}
or this - using virtual function to return type
#include <iostream>
#include <vector>
enum
{
CIRCLE,
RECTANGLE,
UNKNOWN
};
class Circle;
class Rectangle;
class Shape {
private:
Shape() {};
public:
virtual ~Shape() {};
friend class Circle;
friend class Rectangle;
virtual unsigned iAmA(){return UNKNOWN;};
};
class Creator {
public:
virtual ~Creator() {};
virtual Shape* create() = 0;
virtual bool equals(Shape& s) { return false; };
};
class Circle : public Shape {
private:
Circle() : Shape() {};
virtual unsigned iAmA(){return CIRCLE;};
public:
class CircleCreator : public Creator {
public:
CircleCreator() {};
virtual Shape* create() { return new Circle(); };
virtual bool equals(Shape& other_shape) { return (CIRCLE == other_shape.iAmA()); };
};
};
class Rectangle : public Shape {
private:
Rectangle() : Shape() {};
virtual unsigned iAmA(){return RECTANGLE;};
public:
class RectangleCreator : public Creator {
public:
RectangleCreator() {};
virtual Shape* create() { return new Rectangle(); };
virtual bool equals(Shape& other_shape) { return (RECTANGLE == other_shape.iAmA()); };
};
};
int main() {
/* First step, build the list */
std::vector<Shape*> shapeList;
std::vector<Shape*>::iterator it;
Rectangle::RectangleCreator rc;
Circle::CircleCreator cc;
Shape* s = cc.create();
Shape* s1 = rc.create();
shapeList.push_back(s);
shapeList.push_back(s1);
/* Second step: check if we've got a shape starting from a creator */
for (it = shapeList.begin(); it != shapeList.end(); ++it) {
if (rc.equals(**it)) {
std::cout << "same shape" << std::endl;
}
}
return 0;
}
I'm not sure what you're trying to do, but I guess this could point you some direction
enum class Shapes
{
Rectangle,
Circle,
...
};
class Shape
{
private:
Shapes m_shape;
protected:
Shape(Shapes shape)
{
m_shape = shape;
}
public:
Shapes GetShape() { return m_shape; } // this is used to check whether two shapes are equal
virtual ~Shape() = default;
};
And now for factory pattern you'd do:
class ShapeFactory
{
public:
static Shape* CreateShape(Shapes shape)
{
switch (shape)
{
case Shapes::Circle:
return new Circle();
// etc.
}
}
};
This feels very redundant and not very clever to me. Also, this can put alot of code into one place.
For the dispatch, you could do (I assume, I'm not really a fan of this concept as it can be made less verbose with a simple template use)
class ShapeCreator
{
public:
virtual Shape* Create() = 0;
virtual ~ShapeCreator() = default;
};
class Circle : public Shape
{
public:
class Creator : ShapeCreator
{
public:
Shape* Create() { return new Circle(); }
};
Circle() : Shape(Shapes::Circle)
{}
};
bool SomethingWithCircle()
{
Circle::Creator circleCreator;
Shape* first = circleCreator.Create();
Shape* second = circleCreator.Create();
// notice memleak here
return first->GetShape() == second->GetShape();
}
If using C++11, you can go even further and avoid the whole idea /which feels very java-like to me anyway/ using a proper template masturbation techniques. (Can still be applied to pre-C++11, you just won't be able specify the parameters.)
template<class T>
class ShapeCreator
{
public:
template<class... TParams>
static T* Create(TParams&&... parameters) { return new T(std::forward<TParams>(parameters)...); }
};
class Rectangle : public Shape
{
private:
int m_width;
int m_height;
public:
Rectangle(int width, int height) : Shape(Shapes::Rectangle)
{
m_width = width;
m_height = height;
}
};
bool DoSomethingWithRectangles()
{
Rectangle* first = ShapeCreator<Rectangle>::Create(10, 15);
Shape* second = ShapeCreator<Rectangle>::Create(20, 25);
// notice memleak here
return first->GetShape() == second->GetShape();
}
TL;DR
You don't really need RTTI but you need to store the type info somewhere in the base type. I'm using the enum Shapes for this.
Both Factory and Dispatch may seem as a good idea, but you will still need dynamic casting somewhere when using them.
You can replace those two patterns using templates, but as soon as you'll get a vector of the base objects, you'll still have to dynamic_cast at some point.
I didn't measure this whatsoever, but I'm really interested in performance comparison of using virtual functions and dynamic cast as I imagine they'd be very similar...
End note:
Please notice, that I personally feel that using methods like equals or operator== on classes defining the basic interface is not very wise, since there are two possible outcomes:
The equals is virtual -> slow but acceptable
The equals is not virtual -> cannot be used in inherited types to actually do more advanced/relevant comparison, breaking the idea of Open to extension, closed for modification
Obviously, if you don't define the equals, you'd have to write comparison code every time. Or possibly use some templated Comparison class with possible specializations through traits yielding again the best performance with no code duplicity.
Generally speaking, you can get to point where you'd ask yourself "why isn't there base object and reflection like in java or c# in c++? It would allow me to use all these nice and clever patterns." The answer is templates. Why do it run-time, when you can do it compile time?

Comparing objects avoiding dynamic cast [duplicate]

Imagine I have abstract base class Shape, with derived classes Circle and Rectangle.
class Shape {};
class Circle : public Shape {};
class Rectangle : public Shape {};
I need to determine if two shapes are equal, assuming I have two Shape* pointers. (This is because I have two instances of vector<Shape*> and I want to see if they have the same shapes.)
The recommended way to do this is double dispatch. What I've come up with is this (greatly simplified here, so that shapes are equal to all other shapes of the same type):
class Shape {
public:
virtual bool equals(Shape* other_shape) = 0;
protected:
virtual bool is_equal(Circle& circle) { return false; };
virtual bool is_equal(Rectangle& rect) { return false; };
friend class Circle; // so Rectangle::equals can access Circle::is_equal
friend class Rectangle; // and vice versa
};
class Circle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
protected:
virtual bool is_equal(Circle& circle) { return true; };
};
class Rectangle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
protected:
virtual bool is_equal(Rectangle& circle) { return true; };
};
This works, but I have to add a separate equals function and friend declaration in Shape for each derived class. Then I have to copy-paste the exact same equals function into each derived class, too. This is an awful lot of boilerplate for say, 10 different shapes!
Is there a simpler way to do it?
dynamic_cast is out of the question; too slow. (Yes, I benchmarked it. Speed matters in my app.)
I tried this but it doesn't work:
class Shape {
public:
virtual bool equals(Shape* other_shape) = 0;
private:
virtual bool is_equal(Shape& circle) { return false; };
};
class Circle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
private:
virtual bool is_equal(Circle& circle) { return true; };
};
class Rectangle : public Shape {
public:
virtual bool equals(Shape* other_shape) { return other_shape->is_equal(*this); };
private:
virtual bool is_equal(Rectangle& circle) { return true; };
};
equals() always returns false, even on identical shapes. It seems dispatch is always choosing the is_equal(Shape&) base function, even when a "more specific" match is available. This probably makes sense but I don't understand C++ dispatch well enough to know why.
When you create methods like this:
virtual bool is_equal(Shape& circle) { return false; };
And in the subclass,
virtual bool is_equal(Circle& circle) { return true; };
These are not the same method. You have two separate virtual methods, neither of which is overridden (they are overloaded not even overloaded, as Ben Voigt pointed out). When you call Shape::is_equal, there is only one version: Shape::is_equal(Shape&)... which is not overridden and always returns false.
You would have to define the separate overloaded methods in the parent class and then override them in the child class. For example,
class Shape {
// Choice between these two methods happens at compile time...
virtual bool is_equal(Circle& circle) { return false; };
virtual bool is_equal(Rectangle& circle) { return false; };
};
class Rectangle : Shape {
// Choice between this and Shape::is_equal(Rectangle&) happens at runtime...
virtual bool is_equal(Rectangle& circle) { return true; };
};
However, using tricks like this, you will probably not approach the performance or simplicity of the way a C programmer would do it:
typedef enum {
SHAPE_CIRCLE,
SHAPE_RECTANGLE
} shape_type_t;
struct shape {
shape_type_t type;
};
struct circle {
shape_type_t type;
...
};
struct rectangle {
shape_type_t type;
...
};
bool shape_equal(struct shape *x, struct shape *y)
{
if (x->type != y->type)
return false;
switch (x->type) {
case SHAPE_CIRCLE:
return circle_equal((struct circle *) x, (struct circle *) y);
case SHAPE_RECTANGLE:
...;
}
}
If overloading and virtual methods are making your code more complicated than the C version, then you may wish to rethink whether you solve this particular problem with overloading and virtual methods.
Double-dispatch has been well studied. The generalization of double-dispatch is called a "multi-method".
Chapter 11 of Modern C++ Design addresses this issue in detail. The approach using dynamic_cast<> that you described is in section 11.3 "Double Switch-on-Type: Brute Force". The author even describes how to automate most of the work and automatically generate the symmetric overloads. Then, the author introduces a logarithmic dispatch based on std::map<> and std::type_info. Finally, the section ends with "Constant-Time Multimethods: Raw Speed" that's (roughly) based on a matrix of callback functions.
The presented solution includes lengthy explanations on handling functors and casts to avoid nasty pitfalls in presence of multiple (and virtual) inheritance.
If you consider implementing multi-methods in C++, I stronly recommend that you read the book and implement the proposed solution.
You could use a type enumeration and static casting if dynamic_cast is too slow...
enum ShapeType
{
SHAPE_TYPE_CIRCLE,
SHAPE_TYPE_RECTANGLE
};
struct Shape
{
virtual ShapeType GetShapeType() const = 0;
virtual bool isEqual(const Shape& other) const = 0;
};
struct Circle : Shape
{
virtual ShapeType GetShapeType() const { return SHAPE_TYPE_CIRCLE; }
virtual bool isEqual(const Shape& other) const
{
if (other.GetShapeType() == SHAPE_TYPE_CIRCLE)
{
const Circle *circle = static_cast<const Circle*>(&other);
// do some circle specific comparison
return true;
}
return false;
}
};
Virtual functions can easily replace dynamic_cast RTTI type-checking, like this: http://ideone.com/l7Jr5
struct Shape
{
struct subtype { enum { Shape, Circle, Rectangle, ColoredCircle }; };
virtual bool is_a( int type ) const { return type == subtype::Shape; }
virtual bool is_equal(const Shape& s) const { return false; }
};
struct Rectangle : Shape
{
virtual bool is_a( int type ) const { return type == subtype::Rectangle || Shape::is_a(type); }
virtual bool is_equal(const Shape& s) const
{
if (!s.is_a(subtype::Rectangle)) return false;
const Rectangle& r = static_cast<const Rectangle&>(s);
return true; // or check width and height
}
};
struct Circle : Shape
{
virtual bool is_a( int type ) const { return type == subtype::Circle || Shape::is_a(type); }
virtual bool is_equal(const Shape& s) const
{
if (!s.is_a(subtype::Circle)) return false;
const Circle& c = static_cast<const Circle&>(s);
return true; // or check radius
}
};
struct ColoredCircle : Circle
{
virtual bool is_a( int type ) const { return type == subtype::ColoredCircle || Circle::is_a(type); }
};
int main(void)
{
Rectangle x;
Shape y;
return x.is_equal(y);
}
--
Why are there 10 copies of the "exact same" function? Shouldn't Rectangle::is_equal(const Rectangle&) const be comparing Rectangle-specific members?
If all rectangles fall into a single equivalence class, as is the case with the code you showed, then you can just have a single virtual function that returns the equivalence class.
In my designs, I move the Shape::operator== method to private and not implement it. The amount of work to correctly resolve this is not worth the effort.
In other words, given a vector of Shape *:
std::vector<Shape *> my_shapes;
I can do the following:
my_shapes.push_back(new Rectangle);
my_shapes.push_back(new Circle);
The problem comes in when comparing objects:
Shape * p_shape_1 = my_shapes[0];
Shape * p_shape_2 = my_shapes[1];
if (*p_shape_1 == *p_shape_2) {...}
The expression is equivalent to:
p_shape_1->operator==(*p_shape_2);
If a virtual or polymorphic operation is in place, this becomes:
Rectangle::operator==((Circle));
In otherwords, there is a great possibility that Rectangle will be comparing itself to a Circle or other Shape; an invalid comparison.
So, in my designs I prohibit equality comparisons based on base class pointers. The only stuff that can be compared using pointers to base classes is the content in the base class.
I usually refer to dynamic_cast and virtual funcntions. If the compiler is not too dumb, dynamic casting one step is not that different than making two jumps in a vtable.
class shape
{
protected:
virtual bool is_equal(const shape* s) const=0;
friend bool oeprator==(const shape& a, cost shape& b)
{ return a.is_equal(&b); }
};
class circle: public shape
{
double radius;
point<duouble> center;
protected:
virtual bool is_equal(const shape* s) const
{
const circle* p = dynamic_cast<const circle*>(s);
return p && p->radius==radius && p->center==center;
}
};
Same for rectangle or whatever other shape.
basically, dual dispatch requires - if N are the classees, N2 functions.
In this way, you just need N functions (one per class).
If you feel dynamic cast to be too slow, you can use an enum, declared in the base class,
and initialized properly by the derived classes.
But this requires you to update the enum values every time a new class will be added.
For example:
class shape
{
protected:
enum shapes_type { no_shape, circle_shape, rectangle_shape };
shapes_type my_type;
virtual bool is_equal(const shape* s) const=0;
friend bool oeprator==(const shape& a, cost shape& b)
{ return a.is_equal(&b); }
shape() :my_type(no_shape)
{}
};
class circle: public shape
{
double radius;
point<duouble> center;
protected:
virtual bool is_equal(const shape* s) const
{
const circle* p = static_cast<const circle*>(s);
return my_type == s->my_type && p->radius==radius && p->center==center;
}
public:
circle() { my_type = circle_shape; }
};
In case relying on a base_defined enum is not acceptable (not known number of possible classes), you can rely on a simple value (e.g.: an integer) that can represent univocally a type with a trick like:
int int_generator()
{ static int x=0; return ++x; }
template<class T>
int id_for_type()
{ static int z = int_generator(); return z; }
class shape
{
...
int my_type;
};
class circle
{
...
circle() { my_type = id_for_type<circle>(); }
};

Best way to work with an abstract class member in an abstract base class?

I'm not happy with the question title, but I couldn't describe it well. I'm putting implementation in the class declarations for sake of brevity.
I have a class like this:
class VisibleObject {
public:
void draw(sf::RenderWindow& rw) {
rw.draw(*shape.get());
}
virtual void setSize(sf::Vector2f) = 0;
protected:
std::shared_ptr<sf::Shape> shape;
}
sf::Shape is an abstract class. Then I have a derived class like so:
class Brick : VisibleObject {
Brick() {
shape.reset(new sf::RectangleShape());
}
void setSize(sf::Vector2f newSize) {
std::dynamic_pointer_cast<sf::RectangleShape>(shapes).get()->setSize(newSize);
}
}
sf::RectangleShape() is a concrete class that inherits from sf::Shape and setSize() is defined for it, not sf::Shape, which is why I need to cast.
Of course, I need to do some error handling, in the case that the dynamic cast fails and returns an empty shared_ptr.
I'm doing this because I wanted to be able to define the draw method just once, since in this simple game, every object will draw their member this way. Originally I left the shape out of the base class, and e.g. Brick would just have its own private sf::RectangleShape that could get instantiated on the stack; which was clean, but then the draw method had to be re-written for each object type.
This works, but is uglier to work with and introduces heap allocation. I also have shared_ptr overhead (I would have used unique_ptr, but I needed dynamic casting).
Is this the most appropriate way of doing what I'm trying to do?
It might be preferable to keep the interface an interface, and not start mandating implementation details. So just have an empty base class like so:
class VisibleObject
{
public:
~VisibleObject() {}
virtual void draw(sf::RenderWindow & window) = 0;
virtual void setSize(sf::Vector2f const & size) = 0;
};
You can stick the shape storage into the concrete class that implements this interface.
Moreover, Shape should provide a virtual resize method:
class Shape
{
public:
virtual ~Shape() {}
virtual void resize(sf::Vector2f const & size) = 0;
};
Now you can make, say, a VisibleShapeObject as an intermediate base class:
class VisibleShapeObject : public VisibleObject
{
public:
virtual void draw(sf::RenderWindow & window) override final
{
window.draw(*shape_);
}
virtual void setSize(sf::Vector2f const & size) override final
{
shape_->resize(size);
}
protected:
std::shared_ptr<Shape> shape_; // or unique_ptr<Shape>
};
Instead of mandating storage in std::shared_ptr<sf::Shape>, why not simply introduce a means of retrieving an sf::Shape& from the concrete class?
class VisibleObject {
virtual sf::Shape& getShape() = 0;
public:
void draw(sf::RenderWindow& rw) {
rw.draw(getShape());
}
virtual void setSize(sf::Vector2f) = 0;
};
class Brick : VisibleObject {
sf::RectangleShape shape;
sf::Shape& getShape() override { return shape; }
public:
void setSize(sf::Vector2f newSize) override {
shape.setSize(newSize);
}
};
It seems ridiculous to store via a pointer to base, introducing indirections and downcasts and reference count overhead, when you could just store a plain old member. In fact, if I'm understanding the problem correctly, you could probably use a template to generate concrete classes and avoid a lot of boilerplate:
class VisibleObject {
public:
virtual ~VisibleObject() {}
virtual void draw(sf::RenderWindow&) = 0;
virtual void setSize(sf::Vector2f) = 0;
};
template <typename Shape>
class VisibleConcreteObject : public VisibleObject {
Shape shape;
public:
void draw(sf::RenderWindow& rw) override /* final? */ {
rw.draw(shape);
}
void setSize(sf::Vector2f newSize) override /* final? */ {
shape.setSize(newSize);
}
};
typedef VisibleConcreteObject<sf::RectangleShape> Brick;
You haven't shared everything you are trying to do, but this it one way:
template<ShapeT>
class VisibleObject {
public:
void draw(sf::RenderWindow& rw) {
rw.draw(*shape.get());
}
virtual void setSize(sf::Vector2f) = 0;
protected:
std::shared_ptr<ShapeT> shape;
void reset(ShapeT* shape) {
this->shape = shape;
}
}
class Brick : VisibleObject<sf::RectangleShape> {
Brick() {
shape.reset(new sf::RectangleShape());
}
void setSize(sf::Vector2f newSize) {
shape->setSize(newSize);
}
}
There may be reasons why this doesn't work for you, but without more insight, I couldn't guess at what.

C++ Overridden method not getting called

Shape.h
namespace Graphics {
class Shape {
public:
virtual void Render(Point point) {};
};
}
Rect.h
namespace Graphics {
class Rect : public Shape {
public:
Rect(float x, float y);
Rect();
void setSize(float x, float y);
virtual void Render(Point point);
private:
float sizeX;
float sizeY;
};
}
struct ShapePointPair {
Shape shape;
Point location;
};
Used like this:
std::vector<Graphics::ShapePointPair> theShapes = theSurface.getList();
for(int i = 0; i < theShapes.size(); i++) {
theShapes[i].shape.Render(theShapes[i].location);
}
This code ends up calling Shape::Render and not Rect::Render
I'm assuming this is because it is casting the Rect to a Shape, but I don't have any idea how to stop it doing this. I'm trying to let each shape control how it is rendered by overriding the Render method.
Any ideas on how to achieve this?
Here's your problem:
struct ShapePointPair {
Shape shape;
Point location;
};
You are storing a Shape. You should be storing a Shape *, or a shared_ptr<Shape> or something. But not a Shape; C++ is not Java.
When you assign a Rect to the Shape, only the Shape part is being copied (this is object slicing).
This problem is called slicing - you lose the derived functionality when copying to a base.
To avoid this use pointers to the base class, i.e.
std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);
The problem is that in your vector you are storing copies of Shape objects, and copying a Shape object does not copy the data or functionality of its derived classes - you're slicing the polymorphism away.
Manage the objects using new and delete, and arrange for your vector to store pointers to them.
The polymorphism will only work from a pointer to a shape, not from a shape object.
You are accessing the shape object directly for the override to work you need to access the object via a pointer or references.
For example when you assigne the Shape into the ShapePointPair the code will 'slice' the object and only copy the Shape bit into the ShapePointPair
Doing this will mean you have to watch memory management - so you could use a smart pointer in the struct
ShapePointPair {
smart_pointer shape;
Point location;
};
No, it is not casting.
You can instead store a reference to baseclass Point:
struct ShapePointPair {
Shape shape;
Point &location;
};
This reference must be set at construction time for struct
ShapePointPair. Add a constructor to ShapePointPair for this
purpose. It must be passed (newly created) instances of
Rect.
Also observe the memory management responsiblities (proper
written destructors, etc.).
You could try boost::ptr_vector
http://www.boost.org/doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html
I'm not sure to explain well because of my english is poor.
I think you should have to use it reference or pointer type.
because shape is exactly defined what it has to do.
If you use your code directly, your child try to copy and do shape's working.
That is why doesn't work your override function.
use pointer or reference
like this.
pointer.h
class Parent {
public:
virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
Parent* obj1;
Parent* obj2;
};
int main() {
Child1 child1;
Child2 child2;
Holder holder = { &child1, &child2 };
holder.obj1->work();
holder.obj2->work();
return 0;
}
reference.h
class Parent {
public:
virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
Parent& obj1;
Parent& obj2;
};
int main() {
Child1 child1;
Child2 child2;
Holder holder = { child1, child2 };
holder.obj1.work();
holder.obj2.work();
return 0;
}
*ps: personally i use abstract function(virtual void something() = 0;).
because i also forgot about it sometimes so i catch it as syntax error.