lundi 2 avril 2018

std::move with a unique pointer of a base class pointing to an instance of a derived class

I am attempting to implement the command and strategy design patterns in C++.

I have an interface for a command, and an interface for a strategy (a different strategy is assigned to each player, so a player may be manual, AI aggressive, AI defensive, AI random... etc). The strategies have a series of functions which return a unique pointer of type ICommand (eg the command interface) which point to an instance of a derived command class. The idea is to create some command in my strategy in a particular way, and then return the unique pointer to the particular command to the game (the invoker of commands) which execute the commands, regardless of what that command is.

My following questions are these:

  • if I move an instance of a derived class which is pointed to by a unique pointer of a base class, will I get object slicing?

  • if so, what would be a better way of handling moving around objects regardless of their type ?

Here is my code. Note that I only included the code for the command choose_combo, as the rest would be somewhat redundant:

I have an interface for my standard command:

class Igame_command {
protected: // protected, since Igame_command is an interface.
    player &p;
    game_model &gm;

    Igame_command(player p, game_model gm) : p(p), gm(gm) {}

public:
    virtual void execute() = 0;
};

I then have some derived class which implements the above interface:

class choose_combo_c : private Igame_command {
    combo c;
    int vp;
public:
    void set_combo(combo c) { this->c = c; }
    void set_vp(int vp) { this->vp = vp; }
    combo get_combo() { return c; }
    int get_vp() { return vp; }
    choose_combo_c::choose_combo_c(player &p, game_model &gm);

    void execute() override;
};

I then have an interface for my strategy:

class Istrategy {
protected:
application &app;
game_model &gm;
player &p;

Istrategy(application &app, game_model &gm, player &p) : app(app), gm(gm), p(p) {}

public:

virtual std::unique_ptr<Igame_command> choose_combo(
        std::vector<combo> &available_combos, std::vector<int> &available_combos_vp) = 0;

};

For example, for the manual strategy, choosing combo:

std::unique_ptr<Igame_command> manual_strategy::choose_combo(
        std::vector<combo> &available_combos, std::vector<int> &available_combos_vp) override {

    // code to have the player make a choice, it sets the int choice...    

    choose_combo_c* ccc = new choose_combo_c(p, gm);
    ccc->set_combo(available_combos.at(choice));
    ccc->set_vp(available_combos_vp.at(choice));
    return std::unique_ptr<Igame_command> (new choose_combo_c(std::move(*ccc)));
}

Aucun commentaire:

Enregistrer un commentaire