4

いくつかの異なるタイプ ( Packet1Packet2...) のパケットのシリアル化を行うプロジェクトがあります。それらはすべてPacketHeaderクラスを拡張し、独自のシリアル化を行います

このアプローチは、特にフィールドの数が増えるにつれて、非常に面倒でエラーが発生しやすくなります。

シリアル化のためのよりクリーンでよりOOPおよびC++の方法はありますか(サードパーティのライブラリなし)?

class PacketHeader {
    uint8_t type;
    uint32_t id;
    uint32_t seqNum;

    virtual void serialize(uint8_t *buf, size_t size) {
        int offset = 0;
        PacketHeader n;
        n.type = type;
        n.id = htonl(id);
        n.seqNum = htonl(seqNum);
        memcpy(buf + offset, &(n.type), sizeof(n.type));
        offset += sizeof(n.type);
        memcpy(buf + offset, &(n.id), sizeof(n.id));
        offset += sizeof(n.id);
        memcpy(buf + offset, &n.seqNum, sizeof(n.seqNum));
        offset += sizeof(n.seqNum);
    }
}

class Packet1 : public PacketHeader {
    uint32_t payload;

    virtual void serialize(uint8_t *buf, size_t size) {
        int offset = PacketHeader::size();
        PacketHeader::serialize(buf, size);
        memcpy(buf + offset, &n.payload, sizeof(n.payload));
        offset += sizeof(n.payload);
    }
}
4

1 に答える 1

2

データ メンバーを持つ構造体とクラスでネイティブにシリアル化を行うには、各メンバーのオフセット、サイズ、および型の情報をシリアライザーに供給する必要があります。それが「乱雑」な側面の源であり、どんなに洗練されたデザインであっても避けることはできません。

それに何らかの構造を提供できるヘルパー ライブラリがいくつかありますが、それらは一般的に単なる構文であり、メッセージ タイプの数が増えるにつれて維持するのは依然としてかなり困難です。

代わりに、ネイティブの C++ 構造体/クラス データ メンバーを使用するのではなく、辞書 (キー/値データ オブジェクト) を提供するシステムを検討することをお勧めします。JSON などの標準のシリアル化形式を使用するものもあります。JSONCPP は、これを行う非常によく知られたパッケージです: http://jsoncpp.sourceforge.net/

ほとんどの場合、ソフトウェア システムが成長するにつれてより適切にスケーリングされ、指数関数的なメンテナンスの頭痛の種にならないという利点があります。

バイナリのシリアル化が必要な場合は、BSON、MessagePack、Google Protocol Buffers、および Apache Thrift を調べてください。それらはすべて、C++ 用のライブラリまたはバインディングを提供します。

于 2013-05-09T20:47:27.753 に答える