简体   繁体   中英

A better way to store a structure

Here is a problem:

class DrawingsContainer {
 public:
  std::vector<std::pair<std::string, std::shared_ptr<Drawing>>> getDrawings() { return drawings; }
 private:
  std::vector<std::pair<std::string, std::shared_ptr<Drawing>>> drawings;
};

I have a variable

std::vector<std::pair<std::string, std::shared_ptr<Drawing>>> drawings

I'm using std::pair because I need the items I put into the vector to be in the same order I've placed them so std::map is a no no. (I use this container to draw everything on the screen). std::string is there for search purposes.

class Drawing {
 public:
  // only one can be active, thus both are initialized as nullptr at the start and one type is overwritten on creation
  explicit Drawing(
      std::string act,
      std::unique_ptr<sf::Text> txt = nullptr,
      std::unique_ptr<sf::RectangleShape> rectShape = nullptr
  ) {
    active = std::move(act);
    text = std::move(txt);
    rect = std::move(rectShape);
  }
  std::string getActive() { return active; }
  std::shared_ptr<sf::Text> getText() { return text; }
  std::shared_ptr<sf::RectangleShape> getRect() { return rect; }
 private:
  std::string active;
  std::shared_ptr<sf::Text> text;
  std::shared_ptr<sf::RectangleShape> rect;
};

I don't feel like this is a good solution, because what if I use more than sf::Text and sf::RectangleShape classes in the structure ? feels dirty.

Ideally I would like to have this kind of structure:
[["arena", sf::RectangleShape], ["optionsButton", sf::Text]].
where sf::RectangleShape and sf::Text are derivatives of base class sf::Drawable , of course they have different methods which I need to call. here is a nice explanation demonstrating the hierarchy (first picture) - https://www.sfml-dev.org/documentation/2.4.2/classsf_1_1Drawable.php

So I'm wondering if there is a better way to do this.

It seems that you can use regular polymorphism:

struct Drawing
{
    std::string name;
    std::shared_ptr<sf::Drawable> drawable;
};

So

class DrawingsContainer
{
public:
    const std::vector<Drawing>& getDrawings() const { return drawings; }
private:
    std::vector<Drawing> drawings;
};

Use typedef to reduce the long ugly typenames. Since there may be only one instance of the drawing container, singleton pattern may be used like so.

struct node_t
{
  sf::Text text;
  sf::RectangleShape rect;    
};

class Drawing {
 private:
    std::vector<std::shared_ptr<node_t>> tools_;
};

typedef std::vector<std::pair<std::string, std::shared_ptr<Drawing>>> container_t;

class DrawingsContainer {
 public:
  static const std::unique_ptr<DrawingsContainer>& GetInstance() 
  { 
      static std::unique_ptr<DrawingsContainer> ptr(new DrawingsContainer());      
      return ptr; 
  }
 private:
   DrawingsContainer() {}
  container_t drawings_;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM