Refleksja ? Jak dynamicznie stworzyć fabrykę klas ... ?

0

Witam,

Z dość długiego rozpoznania tematu dowiedziałem się, że C++ nie obsługuje mechanizmu refleksji (no może poza klasą QMetaObject w QT, ale ona potrzebuje konkretnego obiektu do analizy).

Mam za zadanie stworzyć dynamiczną fabrykę klas, która posiadałaby w sobie wszystkie klasy, które dziedziczą po danej klasie bazowej, bez konieczności wpisywania ich do fabryki (miliardami if'ów) po utworzeniu nowej klasy.

Zawsze mogę przetworzyć wszystkie pliki cpp z katalogu i wyciągnąć nazwy tych klas, ale będą to stringi i nie mam pojęcia jak zamienić nazwę klasy zapisaną w stringu na wskaznik na tę właśnie klasę ... (myslalem o jakimś makrze preprocesora odwrotnym do STR, ale jakoś nie doszukałem się).

Jakieś pomysły ?

0
  1. Wpisywanie klas do fabryki, ale bez ifów (na chejlerę one?)
  2. Preprocesor

To się może w jakimś stopniu przydać http://www.vollmann.com/en/pubs/meta/meta/meta.html

2

No to może tak?

struct IRenderer { virtual ~IRenderer() = default; };
struct GLRenderer : public IRenderer { GLRenderer(int) {} };
struct DXRenderer : public IRenderer { DXRenderer(int, int) {} };

enum RendererType { NONE, GL, DX };

template <RendererType type = NONE>
struct Factory
{
    template <typename... Ts> 
    static std::unique_ptr<IRenderer> create(Ts&&...)
    {
        throw std::logic_error("Not implemented");
    }
};

template <>
struct Factory<GL>
{
    template <typename... Ts> 
    static std::unique_ptr<IRenderer> create(Ts&&... params)
    {
        return std::unique_ptr<IRenderer>{std::make_unique<GLRenderer>(std::forward<Ts>(params)...)};
    }
};

template <>
struct Factory<DX>
{
    template <typename... Ts> 
    static std::unique_ptr<IRenderer> create(Ts&&... params)
    {
        return std::unique_ptr<IRenderer>{std::make_unique<DXRenderer>(std::forward<Ts>(params)...)};
    }
};

int main()
{
    auto glRend = Factory<GL>::create(100);
    auto dxRend = Factory<DX>::create(200, 11);
    return 0;
}
2
 
#include <iostream>
#include <map>
#include <string>

struct Base;

class Factory
{
    typedef Base*(*Constructor)(void);
public:
    void registerClass(const std::string& name, Constructor constructor) {
        if (map_.find(name) == map_.end())
            map_[name] = constructor;
    }
    Base* create(const std::string& name) const {
        auto i = map_.find(name);
        return i != map_.end() ? i->second() : 0;
    }
private:
    std::map<std::string, Constructor> map_;
};

struct Base
{
    virtual void info() const = 0;
};

struct Foo : Base
{
    static Base* create() {
        return new Foo();
    }
    void info() const override {
        std::cout << "Foo\n";
    }
};

struct Bar : Base
{
    static Base* create() {
        return new Bar();
    }
    void info() const override {
        std::cout << "Bar\n";
    }
};

int main()
{
    Factory factory;
    factory.registerClass("Foo", &Foo::create);
    factory.registerClass("Bar", &Bar::create);

    Base* foo = factory.create("Foo");
    Base* bar = factory.create("Bar");

    foo->info();
    bar->info();

    return 0;
}
0

Dzięki chłopaki, muszę się jeszcze sporo podszkolić. Pomogliście ! :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1