Nico van Bentum
Nico van Bentum

Reputation: 347

Getting derived member variable through base class pointer

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.

Upvotes: 0

Views: 67

Answers (2)

JannisW
JannisW

Reputation: 195

If I understand your question correctly, there are multiple ways how to solve this issue.

  1. 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.

  2. 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.

Upvotes: 3

Technorambler
Technorambler

Reputation: 81

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.

Upvotes: 0

Related Questions