Как сопоставить строку (ID) с созданием нового объекта подкласса c ++ - PullRequest
0 голосов
/ 17 февраля 2019

Я много исследовал, но я не могу найти ничего, что действительно сработает, или, если это возможно.Мне нужна фабрика объектов или реестр, я не знаю как, и никакие потоки действительно не помогают.Они обычно используют идеи, с которыми я совсем не знаком, поэтому им может быть трудно следовать.

В моем примере у меня есть родительский класс с именем Art и несколько дочерних классов типов Art (например, FireBolt).Я хочу, чтобы пользователь мог свободно добавлять объект FireBolt в свой список Arts без необходимости когда-либо включать объект FireBolt в любом месте.Поэтому, проходя только объект Art, мне нужен способ создать новый дочерний класс Art и вернуть его.Идея заключается в том, что это будет похоже на соглашение о режиме консоли / бога, когда пользователь сможет добавлять все, что ему нравится, в любой момент времени.Я знаю, что в таких играх, как Skyrim, есть эта система идентификации, но я точно не знаю, как это сделать.

Я пытался просто сопоставить строку с объектом 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();
};

1 Ответ

0 голосов
/ 17 февраля 2019

Так что после многих часов игры с вещами у меня есть кое-что, что хорошо.Я не совсем думаю, что то, что я хочу сделать, возможно, или, если это так, я просто понятия не имею, как.Это то, с чем я согласился.

Я создал новый класс под названием 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) для лямбда-функции в статической карте.Лямбда-функция просто вернет новую версию Art, которую мы хотим, если вы введете правильный идентификатор, что позволит ей создать много одинаковых Art, что означает, что мне не нужно каждый раз инициализировать ArtFactory в любом месте,Мне нужно будет # включить все произведения, которые я делаю в этом файле, что, к сожалению, но я считаю, что это необходимо.Если нет, я бы полюбил путь, которого не было.

Исходный файл, файл 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 и замените идентификатор (в данном случае «001A») новым идентификатором иновый класс (FireBolt() в данном случае) с новым классом.

Что мне не нравится в этом, так это то, что если я #include "ArtFactory.h" где-нибудь, я также включил все остальные произведения искусства.Этот метод не устраняет необходимость ссылаться на другие виды искусства, и фактически делает обратное.В этой игре определенные персонажи / враги начинают с определенных искусств / атак, а определенные предметы несут эти искусства / атаки, поэтому будет лучше включить конкретный арт / атаку, которые мне нужны, вместо использования этой фабрики.

Для этого будет полезно реализовать режим консоли / бога, потому что теперь я могу легко перечислить все доступные рисунки и их идентификаторы и вернуть новый.Я искренне надеюсь, что это поможет кому-то в какой-то момент.Я застрял в этой проблеме в течение долгого времени, и я не мог найти хорошие темы.

...