我有一个二进制数据包格式,我必须为其实现一个 C++ 阅读器。该库使用 Qt 4,数据包源可以是任何 QIODevice,例如 QTcpSocket、QFile 或 QBuffer。格式包括数据包格式,每个数据包内部也可能有很多子结构。我需要读者返回以下内容:
- 包头;
- 子结构数组;
- 读取操作的错误状态 - 成功、错误或数据不足(特别是从套接字或其他类型的缓冲设备读取时)。
阅读器 API 有多种可能的方法:
Packet read(Status &status);
- 按值返回,通过引用参数返回错误状态。Packet *read(bool *ok);
- 出错时返回 NULL,或者如果数据不足,ok
则根据该变量将 true 或 false 写入变量(如果不是 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 种方法,但返回一个包含数据包和状态信息的特殊结构,但这会引入另一种“合成”类型,并且仍然会留下一个问题“如果出现错误,数据包字段将包含什么?”
或者我可以采用第三种方法并返回 a QSharedPointer<Packet>
,因此调用者不必手动处理堆。但是Packet
对于 Pimpl 而言,该结构可能已经是一种智能指针(共享类)。也许我可以改用那个内部指针并引入一个isNull()
方法,就像 QString 那样。
有更好的或传统的方法吗?