简体   繁体   中英

Proper way to populate map of member objects and store one member with a smart pointer using RAII

So I am pretty new to C++ and am trying to understand smart pointers and the RAII design pattern. My question is this: say I have an object that contains a map of objects. I want one object at a time to be active, that is a want a pointer that points to one of the objects from the map. What is a proper RAII way to go about it using smart pointers? Below is what I have tried so far.

//StateMachine.h
    std::unique_ptr<GameObject> p1Paddle = std::make_unique<GameObject>(Paddle());
    std::unique_ptr<GameObject> p2Paddle = std::make_unique<GameObject>(Paddle());
    std::unique_ptr<GameObject> ball = std::make_unique<GameObject>(Ball());
//StateMachine.cpp
StateMachine::StateMachine()
{
    gameObjects["p1Paddle"] = std::pair <bool, std::unique_ptr<GameObject>>(false, std::move(p1Paddle));
    gameObjects["p2Paddle"] = std::pair <bool, std::unique_ptr<GameObject>>(false, std::move(p2Paddle));
    gameObjects["ball"] = std::pair <bool, std::unique_ptr<GameObject>>(false, std::move(ball));
}

void StateMachine::ChangeState(std::string key)
{
    activeObject = std::move(gameObjects[key]);
}

Instead of using map and smart-pointer and based on your requirements that you only want a single object type at a given moment of time, perhaps you want a priority queue based implementation instead...

Here's a pseudo implementation:

#include <algorithm>
#include <cstdint>
#include <queue>
#include <string>
#include <vector>

enum class ComponentType {
    PADDLE,
    BALL
};

class Component {
protected:
    ComponentType type_;
    uint32_t id_;
    priority_;

    Component(ComponentType type, uint32_t id, float priority) 
     : type_{type}, id_{id}, priority_{prioity};
public:
    virtual ~Component() {}
    auto type() const { return type_; }
    auto id() const { return id_; }
    auto priority() const { return priority_; }
    
    void updatePriority(float newPriority) { priority_ = newPriority; }         
};

class Paddle : public Component {
private:
    std::string name_;
public:
    Paddle(std::string_view name, float priority) :
      Component(ComponetType::PADDLE, std::stoi(name.data()), priority),
      name_{name} 
    {}

    auto name() const { return name_; }
};

class Ball : public Component {
private:
    std::string name_;
public:
    Ball(std::string_view name, float priority) :
      Component(ComponentType::BALL, std::stoi(name.data()), priority),
      name_{name}
    {}

    auto name() const { return name_; }
};

class CmpFunc {
public:
    int operator(){ const Component& a, const Component& b) {
        return a.priority() > b.priority();
    }
};

class Game {
private:
    //std::vector<Component*> components_;
    std::priority_queue<Component*, std::vector<Component*>, CmpFunc> priority_;
public:
    void initialize() {
        Paddle paddle1("paddle_1", 0.1f);
        Paddle paddle2("paddle_2", 0.2f);
        Ball ball("ball", 0.3f");
        addComponent(&paddle1);
        addComponent(&paddle2);
        addComponent(&ball);
    }

    void addComponent(Component* component) {
        if (component == nullptr)
           throw std::runtime_exception( "invalid component pointer!" );

        //components_.push_back(component);
        priority_.push(component);            
    }

    auto getComponent() {
        if (!priority_.empty()) {
            auto component = priority_.top();
            priority_.pop();
            /*components_.erase(
              std::remove(components_.begin(), components_.end(), component), 
              components_.end()
            );*/
            return component;
        }
        return nullptr;
    }
};

This is just a pseudo example code to show a priority queue... I didn't show any implementation of updating or changing the priority queue of an object, nor did I show, how to directly use it based on some state X of the game or finite-state-machine ... That would be an exercise for you...

I can not say whether this code will compile and run since I typed it out right here and have not yet tested it hence the pseudo code. You can play around with it and try to get it to compile and from there expand it to fit your own needs...

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