Я начал использовать подрывную деятельность после чтения блога Wil Shipleys.
, Таким образом, я начал регистрироваться в коде, одной машине и учетной записи dreamhost. Тогда после того, как я случайно удалил функцию и сохранил мой проект, я знал, что был в глубоком "dudu", но с подрывной деятельностью я просто проверил последнюю версию того файла, и это ни на что не было похоже, произошел.
я использую управление версиями для всего теперь. Я - планирование отодвижения мерзавцу, потому что это быстрее, работы офлайн, занимает меньше места, и о мальчик - он быстрее.
Вы можете найти 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. Примерно:
class Message
{
public:
virtual ~Message();
virtual const std::string& tag() const = 0;
virtual void serialize(std::ostream& out) const;
};
Один из способов приблизиться к этому - использовать карту и зарегистрировать какую-то фабричную функцию для каждого типа сообщения. Это означает, что вы избавляетесь от корпуса переключателя и можете динамически добавлять и удалять сообщения.
Код будет выглядеть примерно так:
// 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;
}
};