2016-07-25 4 views
0

Good EveningКак упростить разработку моделей

В настоящее время я разрабатываю нечто вроде C++ MVC framework. Это просто для образовательных целей прямо сейчас - посмотреть, смогу ли я сделать такую ​​вещь, понять ее полностью и узнать о ней по-другому (не так).

У меня есть абстрактный класс для моделей, которые будут расширены, чтобы создать новый. Они регистрируются одним регистром и загружаются с помощью класса загрузчика по имени строки.

Итак, прямо сейчас, а пустые новые модули написаны таким образом:

# myModel.hpp 

class myModel: public cinite::core::abstract::Model { 
    public: 
     myModel(cinite::core::Loader &_loader): cinite::core::abstract::Model(_loader){}; 

    private: 
     static cinite::core::registerClass<myModel> __cinite_reg; 
}; 

# myModel.cpp 
cinite::core::registerClass<myModel> myModel::__cinite_reg("myModel"); 

Это довольно много сочинительство, поэтому я решил упростить это путем добавления макросов, как

#define CINITE_MODEL_CONSTRUCT(CLASS) \ 
    CLASS(cinite::core::Loader &_loader): cinite::core::abstract::Model(_loader){}; 

#define CINITE_DEFINE_REGISTRY(CLASS) \ 
    static cinite::core::registerClass<CLASS> __cinite_reg; 

#define CINITE_REGISTER(CLASS, NAME) \ 
    cinite::core::registerClass<CLASS> CLASS::__cinite_reg(#NAME); 

Таким образом, сейчас все будет так:

# myModel.hpp 

class myModel: public cinite::core::abstract::Model { 
    public: 
     CINITE_MODEL_CONSTRUCT(myModel); 

    private: 
     CINITE_DEFINE_REGISTRY(myModel); 
}; 

# myModel.cpp 

CINITE_REGISTER(myModel, myModel); 

И, очевидно, это выглядит намного легче r (по крайней мере мне) писать.

Но все еще есть что-то конструктор. Интересно, есть ли возможность обойти это (поскольку это будет выглядеть точно так же для каждого класса, кроме имени класса) и использовать конструктор по умолчанию abstract :: Model? Я бы использовал довольно простой виртуальный метод void __init() без аргументов, если кто-то нуждался в какой-либо инициализации в своей модели и обходил всю загрузчику.

Итак, наконец, Как я могу использовать абстрактную конструкцию по умолчанию: конструктор модели с аргументами для упрощения записи пустых моделей? Мне нужен погрузчик для передачи модели, поскольку это то, что делает все возможное (загрузка других моделей, драйверов и других вещей).

И еще один вопрос с бонусом: Делайте это хорошо, или есть что-нибудь, что делает его ужасным в использовании?

Для одних любопытства - регистратура-вещь выглядит, как это прямо сейчас

# registry.hpp 

namespace cinite { 
    namespace core { 

     template <typename T> 
     abstract::Abstract *abstractCreator(Loader &_loader) { 
      return new T(_loader); 
     } 
     typedef abstract::Abstract* (*abstractCreatorFunc)(); 

     class Registry { 
      public: 
       static Registry& getInstance() { 
        static Registry instance; 
        return instance; 
       } 
       Registry(){}; 
       Registry(Registry const&)  = delete; 
       void operator=(Registry const&) = delete; 

       const static unsigned int t_abstract = 0; 
       const static unsigned int t_model  = 1; 

       ... 

       static void registerModel(std::string name, abstractCreatorFunc creator); 
       static abstractCreatorFunc getModelCreator(std::string name); 

       ... 

      private: 
       std::map<std::string, abstractCreatorFunc> _models; 

       ... 

     }; 

     template<typename T> 
     struct registerClass { 
      registerClass(const std::string name) { 
       switch (T::__regType) { 
        case Registry::t_model: 
         Registry::registerModel(name, (abstractCreatorFunc)abstractCreator<T>); 
         break; 

        ... 
       } 

      } 
     }; 
    } 
} 


# registry.cpp 

using namespace cinite::core; 

void Registry::registerModel(std::string name, abstractCreatorFunc creator) { 
    Registry::getInstance()._models[name] = creator; 
} 

abstractCreatorFunc Registry::getModelCreator(std::string name) { 
    Registry &reg = Registry::getInstance(); 
    std::map<std::string, abstractCreatorFunc>::iterator it; 

    it = reg._models.find(name); 

    if (it == reg._models.end()) { 
     throw exception::registryException(exception::registryException::MODEL_NOT_REGISTERED, "Model not found in registry (" + name + ")"); 
    } 

    return (abstractCreatorFunc)it->second; 
} 

Кстати: решение для реестра происходит от this solution (благодаря @ Johannes-Шауб-LITB).

ответ

1

Не можете использовать ключевое слово using? Например, этот код компилируется:

#include <iostream> 

class A 
{ 
public: 
    A(int a) : mA(a) {} 
    virtual ~A() {} 
    virtual void print() { std::cout << mA << std::endl; } 
protected: 
    int mA; 
}; 

class B : public A 
{ 
public: 
    using A::A; // use the constructor from A 
}; 

int main() 
{ 
    B b(10); 
    b.print(); 
    return 0; 
} 
+0

Да, это отлично выглядит. Именно то, что я искал –