我正在尝试在C ++中实现命令和策略设计模式。
我有一个命令界面和一个策略界面(为每个玩家分配不同的策略,因此玩家可以是手动,AI攻击性,AI防守,AI随机等等)。策略具有一系列函数,这些函数返回ICommand类型的唯一指针(例如命令接口),该指针指向派生命令类的实例。我的想法是以特定的方式在我的策略中创建一些命令,然后将指向特定命令的唯一指针返回给执行命令的游戏(命令调用者),而不管该命令是什么。
我的以下问题是:
如果我移动一个由基类的唯一指针指向的派生类的实例,我会得到对象切片吗?
如果是这样,那么处理物体移动的更好方法是什么?
这是我的代码。请注意,我只包含命令choose_combo
的代码,因为其余部分有点多余:
我有一个标准命令的接口:
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;
};
然后我有一些实现上述接口的派生类:
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;
};
然后我为我的策略设置了一个界面:
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;
};
例如,对于手动策略,选择组合:
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)));
}
答案 0 :(得分:0)
unique_ptr<T>
存储T*
,而不是T
,因此您不会在示例中获得任何对象切片。
但是你确实有内存泄漏,你分配的ccc
对象不是delete
d任何人,你移动构建一个新对象,但泄漏原始本身。 manual_strategy::choose_combo
中的代码应写为
auto ccc = std::make_unique<choose_combo_c>(p, gm); // create a unique_ptr<choose_combo_c>
// do stuff with it
ccc->set_combo(available_combos.at(choice));
ccc->set_vp(available_combos_vp.at(choice));
// simply return it here, a unique_ptr<Igame_command>
// will be constructed from the unique_ptr<choose_combo_c>
return ccc;
答案 1 :(得分:0)
无论如何,你无法“移动”原始指针 - 无意义。您可以有意义地移动unique_ptr
,但这不会将对象移动到任何地方,它只意味着该指向对象的所有权(作为已分配的内存)移动到某个地方/其他人。
处理物体的更好方法是什么?无论其类型如何?
使用指针 实际上是对象“移动”的合理方式,无论其类型如何:您根本不会(或很少)实际移动任何对象,您只需使用指向它们的指针。如果您想要键入遗忘,则可能无法使用键入的unique_ptr
,但您可以将void *
或unique_ptr<void>
指针与自定义删除符一起使用。
另一种选择是使用std::any
,而不使用指针。如果物体很小,移动它们很便宜,如果它们很大,它们就会隐藏指针,所以移动它们又便宜了。从某种意义上来说,这种替代方案更安全,而不是分段违规和重新解释垃圾,如果你尝试错误的类型,你只会得到例外。