SFML - jak uniknąć "object slicing"

0

Cześć,

Natknąłem się na problem slicing'u obiektów przechowywanych w vectorze jako wskaźniki, natomiast sam vector znajduje się w klasie bazowej:

class ModelC : public sf::Drawable
{
public:
    void CreateCircle( const float radius = 0 );

    void CreateRectangle( const sf::Vector2f &size = sf::Vector2f( 0, 0 ) );

private:
    std::vector<std::unique_ptr<sf::Shape>> shapes;
};

Jak widać przechowuję typ ogólny sf::Shape, jednak wrzucam tam typy pochodne jak właśnie na przykład koło i czworobok (sf::CircleShape i sf::RectangleShape).

Problem jest prosty, ale jednak zablokował mnie już na dość długo i najwidoczniej o czymś nie wiem:
Jeśli teraz klasa sf::CircleShape posiada metodę setRadius(), ale klasa sf::RectangleShape już nie, to jak (albo: czy w ogóle) mogę iterując po vectorze zmieniać rozmiar/średnicę elementu, jeśli jest on rozpoznany jako sf::Shape:

void PlayerC::SetSize( const float size )
{
    for( auto it = shapes.begin(); it != shapes.end(); ++it )
    {
        it->get()->setRadius( size );      // NIE
    }
}

stackoverflow mówi mi jedynie, że uniknięcie slicingu można uzyskać przez użycie wskaźników, ale takie rozwiązanie jest już od początku. Czy to w ogóle nadal problem slicing`u? Może jednak problem leży w architekturze?
Jak rozpoznać "pochodny" typ obiektu, który wyciągam z vector'a przechowującego typ bazowy?

0

To nie jest problem slicingu. Aby dostać się do metod klas dziedziczących musisz na nie rzutować. W przypadku klas polimorficznych możesz użyć dynamic_cast lub static_cast, w pozostałych przypadkach wyłącznie static_cast + jakiś enum/inna wartość do sprawdzenia dynamicznego typu obiektu.

Przy czym takie zapotrzebowanie brzmi jakbyś miał gdzieś problem z designem.

0

To nie jest problem slicingu.

Też tak myślałem, stąd moje pytania na koniec.
Jeśli to problem z architekturą, to jaki? Tutaj przypadek wydaje się być dość prosty: Chcę mieć obiekt w systemie, złożony z różnych kształtów, więc tworzę ogólną klasę Model przechowującą zbiór kształtów danego bytu. Potem jest klasa pochodna przedstawiająca konkretny byt, który swoje konkretne kształty przechowuje w tym zbiorze.
Możliwe, że da się to zaprojektować inaczej, a może to kwestia samego kodu?

1

jak masz takie coś std::vector<std::unique_ptr<sf::Shape>> znaczy, że tylko tyle potrzebujesz i w tym miejscu nie interesuje cię żadna inna funkcjonalność, poza tą dostępną z sf::Shape.
Jak chcesz robić inne operację to potrzebujesz vector dla innego interface'u, albo wręcz innej organizacji obiektów.
Bez detali trudno powiedzieć jak to ma być.
A wszelkie dynami_cast i static_cast w tym wypadku, będą tylko oznakami, że z kodem coś jest nie tak.

1 użytkowników online, w tym zalogowanych: 0, gości: 1