Выбор правильного подкласса для инстанцирования программно

Я начал использовать подрывную деятельность после чтения блога Wil Shipleys.

, Таким образом, я начал регистрироваться в коде, одной машине и учетной записи dreamhost. Тогда после того, как я случайно удалил функцию и сохранил мой проект, я знал, что был в глубоком "dudu", но с подрывной деятельностью я просто проверил последнюю версию того файла, и это ни на что не было похоже, произошел.

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

6
задан Cœur 21 January 2019 в 10:11
поделиться

2 ответа

Вы можете найти LibTomCrypt полезным. Он написан на C, поддерживает RSA и DSA (наряду с множеством других алгоритмов) и является общественным достоянием. Вы можете прочитать об этом здесь .

и еще один для парсеров
  • Каждое сообщение имеет как тег, так и связанный с ним синтаксический анализатор
  • Давайте посмотрим на код:

    // Framework
    class Message
    {
    public:
      virtual ~Message();
    };
    
    class Parser
    {
    public:
      virtual ~Parser();
      virtual std::auto_ptr<Message> parse(std::istream& serialized) const;
    };
    
    // Factory of Messages
    class MessageFactory
    {
    public:
      void register(std::string const& tag, Parser const& parser);
      std::auto_ptr<Message> build(std::string const& tag, std::istream& serialized) const;
    private:
      std::map<std::string,Parser const*> m_parsers;
    };
    

    И с этой структурой (по общему признанию простой), некоторые производные классы:

    class MessageA: public Message
    {
    public:
      MessageA(int a, int b);
    };
    
    class ParserA: public Parser
    {
    public:
      typedef std::auto_ptr<MessageA> result_type;
      virtual result_type parse(std::istream& serialized) const
      {
        int a = 0, b = 0;
        char space = 0;
        std::istream >> a >> space >> b;
        // Need some error control there
        return result_type(new MessageA(a,b));
      }
    };
    

    И, наконец, use:

    int main(int argc, char* argv[])
    {
      // Register the parsers
      MessageFactory factory;
      factory.register("A", ParserA());
    
      // take a file
      // which contains 'A 1 2\n'
      std::ifstream file = std::ifstream("file.txt");
      std::string tag;
      file >> tag;
      std::auto_ptr<Message> message = factory.parse(tag, file);
    
      // message now points to an instance of MessageA built by MessageA(1,2)
    }
    

    Это работает, я знаю, потому что использую его (или вариант).

    Есть некоторые вещи, которые следует учитывать:

    • Вы можете сделать MessageFactory синглтоном, this затем позволяет вызывать его при загрузке библиотеки, и, таким образом, вы можете зарегистрировать свои парсеры, создав экземпляры статических переменных. Это очень удобно, если вы не хотите, чтобы main регистрировал каждый отдельный тип парсера: locality> less dependencies.
    • Теги должны быть общими. Также нет ничего необычного в том, что тег обслуживается виртуальным методом класса Message (называемым тегом).

    Примерно:

    class Message
    {
    public:
      virtual ~Message();
      virtual const std::string& tag() const = 0;
      virtual void serialize(std::ostream& out) const;
    };
    
    • Логика для сериализации также должна быть общей,
    6
    ответ дан 8 December 2019 в 14:43
    поделиться

    Один из способов приблизиться к этому - использовать карту и зарегистрировать какую-то фабричную функцию для каждого типа сообщения. Это означает, что вы избавляетесь от корпуса переключателя и можете динамически добавлять и удалять сообщения.

    Код будет выглядеть примерно так:

    // Create the map (most likely a member in a different class)
    std::map<BaseMessage::Type, MessageCreator*> messageMap;
    ...
    
    // Register some message types
    // Note that you can add and remove messages at runtime here
    messageMap[BaseMessage::MyMessageA] = new MessageCreatorT<BaseMessageA>();
    messageMap[BaseMessage::MyMessageB] = new MessageCreatorT<BaseMessageB>();
    ...
    
    // Handle a message
    std::map<Type, MessageCreator*>::const_iterator it = messageMap.find(msgType);
    if(it == messageMap.end()) {
        // Unknown message type
        beepHang();
    }
    // Now create the message
    BaseMessage* msg = it->second.createMessage(data);
    

    Класс MessageCreator будет выглядеть примерно так:

    class MessageCreator {
        public:
        virtual BaseMessage* createMessage(void* data, size_t len) const = 0;
    };
    template<class T> class MessageCreatorT : public MessageCreator {
        public:
        BaseMessage* createMessage(void* data, size_t len) const {
            T* newMessage = new T();
            newMessage.parse(data, len);
            return newMessage;
        }
    };
    
    10
    ответ дан 8 December 2019 в 14:43
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: