如何将字符串(ID)映射到新的子类对象c ++的创建

问题描述 投票:0回答:1

我已经研究了很多,但我似乎找不到任何实际可行的东西,或者它是否可行。我需要的是一个对象工厂或我认为的注册表,我不知道如何,没有线程真正帮助。他们通常会使用我不熟悉的想法,因此很难遵循。

在我的例子中,我有一个名为Art的父类和一组Art类型的子类(例如FireBolt)。我希望用户能够自由地将FireBolt对象添加到他们的Arts列表中,而无需在任何地方包含FireBolt对象。所以只通过Art对象,我需要一种方法来创建一个新的Art子类并返回它。这个想法是它将像一个控制台/神模式类型的交易,用户将能够在任何给定的时间添加他们喜欢的任何东西。我知道Skyrim这样的游戏有这个ID系统,我不知道怎么做。

我试图简单地将字符串映射到Art *对象(std::map<std::string, Art*> artMap),并使用名为regArt(std::string ID, Art* art)的函数,但每当我尝试使用它时,它返回错误“错误:预期的构造函数,析构函数或类型转换之前'('此外,我相信这意味着每个人都会分享Art的单一版本,而在游戏规范中,Art可以在游戏中期改变。

请注意,我已经链接到试图解决相同问题的其他线程,但我无法让它们在我的示例中工作。对答案的很多评论只是说'这不起作用'。

一些可能无用的代码;

Art.h;

class Art {

    std::string name;
    int EPCost;
    int castTime;
    int AoESize;
    std::string ID;

public:
    Art(std::string n, int cp, int ct, int as):name(n), EPCost(cp), castTime(ct), AoESize(as) {}

    virtual ~Art() {}


    int getAoESize() {return AoESize;}

    std::string getName() {return name;}
    int getEPCost() {return EPCost;}

    virtual int getBaseDamage() = 0;
};

FireBolt.h;

class FireBolt:public Art {
    static const std::string name;
    static const int EPCost;
    static const int castTime;
    static const int AoESize;

public:
    FireBolt():Art(name, EPCost, castTime, AoESize) {}

    ~FireBolt() {}

    int getBaseDamage();
};
c++ registry factory
1个回答
0
投票

因此,经过几个小时的玩游戏,我有一些可以做的事情。我不完全认为我想做的事情是可能的,或者如果它是我根本不知道如何。这就是我解决的问题。

我创建了一个名为ArtFactory的新课程(未决定是否仅使用以下标题和源文件将其扩展到游戏中的所有内容,即设备,攻击等);

ArtFactory.h;

#include "Arts.h"
#include "FireBolt.h"
#include <functional>

class ArtFactory {
    static std::map<std::string, std::function<Art*()>> artMap;
public:
    ArtFactory();

    static void loadArts();
    static Art* getNewArt(std::string ID) {return artMap.find(ID)->second();}
    static void regArt(std::string ID, std::function<Art*()> f) {artMap[ID] = f;}
};

这会将字符串(ID)映射到静态映射中的lambda函数。如果你输入正确的ID,lambda函数将简单地返回我们想要的新版本的Art,从而允许它生成许多相同的Art,这意味着我不是每个人都必须在任何地方初始化ArtFactory。我需要#include我在这个文件中制作的每一件艺术品,这很不幸,但我认为这是必要的。如果没有,我会喜欢一种不需要的方式。

源文件,cpp文件;

#include "ArtFactory.h"

std::map<std::string, std::function<Art*()>> ArtFactory::artMap;


ArtFactory::ArtFactory() {
    return;
}

void ArtFactory::loadArts() {
    artMap["001A"] = []() -> Art* {return new FireBolt();};
}

然后展开它,只需复制loadArts中的行,并用新ID替换ID(在本例中为“001A”),并用新类替换新类(在本例中为FireBolt())。

我不喜欢这个,如果我在任何地方加入#include "ArtFactory.h",我还包括其他所有艺术品。这种方法并不能消除与其他艺术相关的需要,事实上恰恰相反。在这个游戏中,某些角色/敌人从某些艺术/攻击开始,某些物品带有这些艺术/攻击,所以包含我需要的特定艺术/攻击而不是使用这个工厂会更好。

实现控制台/神模式将会有什么用处,因为我现在可以轻松列出每个可用的艺术品和它的ID,并返回一个新的艺术。我真诚地希望这在某些方面对某人有所帮助。我被困在这个问题很长一段时间,我找不到任何好的线程。

© www.soinside.com 2019 - 2024. All rights reserved.