C++ Overridden method not getting called - c++

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.

Related

how to make static "polymorphic" member variables

Basically what I am trying to do here is make an ID for each derived type of Shape. ( Square is 1, Circle is 2, etc.)
How can I make a static member variable that has polymorphic capabilities? How would I create the getters and setters?
class Shape {
public:
Shape() {}
static int ID;
};
class Square : public Shape {
public:
Square() {}
};
class Circle : public Shape {
public:
Circle() {}
};
class Person {
public:
int shape_type_ID
Shape* ptr;
Person(){}
};
int Shape::var{ 5 };
Is this a copy of this question?
How to initialize `static` member polymorphically
EDIT:
In my current design, each instance of Person contains a pointer ( I am not sure about the type of pointer ) that points to some Shape object. I want to restrict each Person object to only being able to reference one derived type of Shape.
E.g. Person 1’s pointer can only reference Circles, Person 2’s pointer can only reference Squares, Person 3’s pointer can only reference Triangles.
But I want 1 single Person class with 1 type of pointer ( probably Shape ). In theory that should be do-able. One of the problems is that there should be as many Person objects as there are Shape derived types (one for Square, one for Circle, one for Triangle). How do I know how many Person objects to make?
When you want polymorphism you should use virtual methods, not static members.
class Shape {
public:
virtual int ID(){ return 0; }
virtual ~Shape(){}
};
class Square : public Shape {
public:
virtual int ID() override { return 1;}
};
class Circle : public Shape {
public:
virtual int ID() override { return 2; }
};
you can do something like this if you really need to, but I suggest just making a constructor in base that accepts an id and pass it from the childs to the parent
int getNextId()
{
static int lastId{0};
return lastId++;
}
template<typename T>
int getDerivedId()
{
static int id{getNextId()};
return id;
}
struct Base {
};
struct Derived0 final : Base {
};
struct Derived1 final : Base {
};
int main() {
return !(getDerivedId<Derived0>() == 0 && getDerivedId<Derived1>() == 1);
}

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.

Cannot use dynamic_cast to convert from Base to Derived

I get an error when I try to cast base class to derived class.
I want to access the derived classes that I have put in my components vector.
//Base and Derived
class Component
{
public:
Component();
virtual ~Component();
private:
};
class Material:public Component{...};
//in main
int textureID = gameScene.gameObjects[0].getComponent<Material>()->texture;
//game object
#pragma once
#include <vector>
#include "Component.h"
class GameObject:public Component
{
public:
GameObject();
GameObject(int otherAssetID);
~GameObject();
int assetID;
std::vector<Component> components;
void addComponent(Component otherComponent);
void deleteComponent(Component otherComponent);
template <class T>
T* getComponent() {
for (int i = 0; i < components.size(); i++)
{
if (dynamic_cast<T*>(components[i]) != nullptr)
{
T *test = dynamic_cast<T*>(components[i]);
return test;
}
}
return nullptr;
}
private:
};
std::vector<Component> can not contain objects of class other than Component itself. If you add a Material object to the vector, the Component part of the Material will be stored. That problem is known as the object slicing problem.
You probably want to make a vector holding pointers to the base polymorphic class.
::std::vector<::std::unique_ptr<Componenet>> components;
also dynamic_cast is expensive so you may want to call it only once storing returned value:
T * const test = dynamic_cast<T*>(components[i].get());
if(test)
{
return test;
}

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++ Keeping a reference /pointer of an abstract type

I'm new to c++ and this question probably seems noobish as I'm just more of a Java/Actionscript3 and I've never dealt with memory related things before.
Anyhow as for the problem I have:
Scene is an abstract class (so I can derive from it and have multiple scenes, like MainScene etc')
What I wanted SceneManager to do is have a pointer / reference to the selected scene (curSc)
And then I'd set the scene like so: setScene(&someScene)
But as I understand, to have a pointer I must also initialize it like so:
curSc = new Scene;
But it won't let me do that as Scene is an abstract class..
class Scene {
public:
Scene(void){}
virtual ~Scene(void){}
virtual void update() = 0;
virtual void render() = 0;
};
class SceneManager {
public:
SceneManager(void);
~SceneManager(void);
void setScene(Scene *sc);
Scene* curSc;
}
So far it seems to me like using a pointer in this case is wrong and it won't work..
But I'd love to know how to achieve the functionality I'm trying to obtain here
Thank you very much
Edit by request:
that's how I tried to use it:
Firstly I have a derived class named GameScene and here it is:
class GameScene : public Scene
{
public:
GameScene(void);
void render();
void update();
}
in my main() function I have:
GameScene gamescene;
ScreenManager manager;
manager.setScene(&gamescene);
you need a concrete derived class of Scene:
class MyScene: public Scene {
public:
MyScene(void){}
virtual ~MyScene(void){}
virtual void update();
virtual void render();
};
And void setScene(Scene *sc) will be:
void setScene(Scene *sc)
{
curSc = (Scene*)sc;
}
sc will be MyScene pointer in this case. Abstract class instances (ie interfaces) can not be created and Scene is just an interface here.
Exactly. You can not do
curSc = new Scene
because it is abstract. If you actually want to declare an instance of Scene then make it non abstract. i.e. implement all the methods.
OR (I think this is what you intended to do) create a class that inherits from Scene and implements all the virtual methods.
class View : public Scene {
public:
View(){}
virtual ~View(void){}
virtual void update();
virtual void render();
};
and implement the virtual methods like
void View::update() {
//
}
void View::render() {
//
}
Then you can implement setScene as
void SceneManager::setScene(Scene *sc)
{
curSc = sc;
}
and call it like
SceneManager smag;
Scene *nsc = new View;
smag.setScene(nsc);
It is not wrong to use pointer here. But unlike a reference, a pointer urges its user to account for NULL. That is the caveat. Reference can refer to NULL as well, but adding defense against it will lead you to the "dark side". So, it is reasonable to assume reference will refer to alive object and in this sense references are better than pointers.
Now, if you really-really want to keep the reference you can use in-place construction technique, because you can (re)assign reference by constructor:
class SceneManager {
public:
SceneManager(Scene& sc) : curSc(sc) {}
~SceneManager(void);
SceneManager& setScene(Scene &sc) {
SceneManager* cheatCompiler = new(this) SceneManager(sc);
return *cheatCompiler;
}
Scene& curSc;
}
Note, that this is kind of quirky stuff. Since compilers try to outsmart us all the time, I can not guarantee it will work in all cases.
That said I would still recommend you using the pointer. If you dont want to check for NULL all the time, you can implement something like Null Object Pattern.
You should use smart pointers, and do not make member variables public. Example:
class Scene {
public:
virtual ~Scene(){}
virtual void update() = 0;
virtual void render() = 0;
};
class MyScene : public Scene {
public:
virtual void update () { /*...*/ }
virtual void render () { /*...*/ }
};
class SceneManager {
public:
SceneManager();
~SceneManager();
void setScene(const std::shared_ptr<Scene> & sc) {
curSc = sc;
}
private:
std::shared_ptr<Scene> curSc;
};
void someProc () {
std::shared_ptr<Scene> sc = std::make_shared<MyScene> ();
auto manager = std::make_shared<SceneManager> ();
manager->setScene (sc);
// ...
}
Without smart pointers, this would look like (but remember to delete the objects created with new if they are not needed anymore):
class Scene {
public:
virtual ~Scene(){}
virtual void update() = 0;
virtual void render() = 0;
};
class MyScene : public Scene {
public:
virtual void update () { /*...*/ }
virtual void render () { /*...*/ }
};
class SceneManager {
public:
SceneManager();
~SceneManager();
void setScene(Scene * sc) {
curSc = sc;
}
private:
Scene * curSc;
};
void someProc () {
Scene * sc = new MyScene;
SceneManager * manager = new SceneManager;
manager->setScene (sc);
// ...
}