我有一个二进制数据包格式,必须为其实现C ++读取器。该库使用Qt 4,并且数据包源可以是任何QIODevice,例如QTcpSocket,QFile或QBuffer。格式包括数据包格式,每个数据包内部也可能有很多子结构。我需要读者返回以下内容:


包头;
子结构数组;
读取操作的错误状态-成功,错误或数据不足(尤其是从套接字或其他类型的缓冲设备读取数据时)。


阅读器API有多种可能的方法:


Packet read(Status &status);-按值返回,并通过引用参数返回错误状态。
Packet *read(bool *ok);-如果错误或如果数据不足,则返回NULL,根据该值将true或false写入ok变量(如果不是NULL)。
Packet *read();-如果错误或数据不足,则返回NULL,请调用另一个方法bool wasError();以检查发生了什么。可以通过使ok参数具有默认值NULL来与前一个合并。
Status read(Packet &packet);-如果返回的状态为Ok,则将读取的值放入packet变量中,否则表示错误或EOF。
Packet read();-按值返回,如果出现EOF或错误,则返回一个特殊的“空包”值。调用wasError()确定发生了什么。


当然,还有其他可能的组合。似乎没有最好的选择。方法1、2和4要求调用者声明一个单独的变量来存储结果。方法2和3涉及弄乱堆,出于明显的原因,我不想这样做。方法1并未明确指出发生错误时返回的内容。方法5修复了该问题,但是在数据包结构中引入了特殊的“空”标志,尽管它可能不属于该结构。

我可以采用第5种方法,但是返回一个包含数据包和状态信息的特殊结构,但这引入了另一种“合成”类型,并且仍然悬而未决的问题“如果发生错误,数据包字段将包含什么?”

或者,我可以采用第三种方法并返回一个QSharedPointer<Packet>,因此调用者不必手动弄乱堆。但是对于Pimpl而言,Packet结构可能已经是一种智能指针(共享类)。也许我可以改用内部指针并引入一个isNull()方法,就像QString一样。

是否有更好的方法或传统的方法?

最佳答案

好吧,我已经将其实现如下。

读取方法的签名是:

Packet readPacket(bool *error = NULL);


Packet类如下所示:

class Packet {
    inline Packet(): p(NULL) {} // this is returned on error or EOF
    Packet(const Header &header, const Data &data);
    inline bool isNull() {return p == NULL;}
private:
    QSharedDataPointer<PacketPrivate> p;
};


如果没有将bool wasError()参数提供给error函数,则数据包读取器还具有readPacket()方法,该方法用于检索错误状态。

该实现使我:


创建像while (!(packet = reader->readPacket()).isNull()) ...这样的优雅循环
为了避免在Packet类中具有不相关的字段,例如“错误”或“空”。
为避免手动分配或删除指针,或避免在调用者端显式弄乱智能指针。
为了避免在使用默认构造函数时具有未初始化的字段。


它仍然很不完善,因为必须提供error参数或稍后调用wasError()。但是我相信,强制调用者检查错误的唯一方法是使用异常,但是出于可移植性的原因,我不想这样做。

关于c++ - 数据包读取器Qt/C++ API设计,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11409222/

10-12 20:41
查看更多