如何处理可选参数+可选return值

How to handle optional parameter + optional return value

问题如下:我有一个 class,它封装了我可以通过对象 ID 查询的某种容器(即地图)。 class 还封装了第二个容器,其中包含属于对象的附加数据(即矩阵)。 我的 class 的客户端应该可以查询对象并决定他是否也想要 returned 的附加数据,即以这种方式:

ObjectData objData;
Object obj = myClass.getObject(objectID, &objData);

然而,如果客户端请求附加数据但他查询的对象没有附加数据链接到它,那么客户端应该能够告诉这一点。 IE。如果我的函数是这样工作的:

Object MyClass::getObject(ObjectID oID, ObjectData* objData)
{
    // ...
    if(objData && this->hasObjectData(oID))
      objData = this->getObjectData(oID);
}

并且客户端以上述方式调用它,getObject 函数识别到查询的对象没有附加数据,并且将保持传递的 objData 指针不变。客户端然后发现自己有一个默认构造的 ObjectData 对象,并且不知道它是默认构造的还是由 getObject 函数 returned 作为参数 return 值。

在我的脑海中,我只能想到或多或少丑陋的解决方案,例如在堆上分配数据,以便用户可以取回空指针或以某种方式向函数调用添加标志。可能更好的设计是完全单独查询 objectData,但上面的方法很好也很容易,所以我想知道是否有一个优雅的解决方案仍然以这种方式进行。

getObject(objectID, &objData);

通过这种方式使用 getObject,您赋予了它两个职责。首先是准备好对象,其次是检查是否可以加载附加信息。我建议将其分为两部分(方法)。

obj = getObject(objectID);  // get the object based on definite 
                            // info i.e 1st container.
if(obj.isMatrixValid)
    obj.setMatrixData();

因此,您在这里将责任分为两种方法。但是,一个缺点是您必须记住在创建后更新 object

Probably a better design would then be to query objectData completely separately

是。

getObject责任太多了。

but the above would be nice and easy

如果客户端实际上并不关心额外的对象数据,那么这会更好更容易:

Object obj = myClass.getObject(objectID)

然后对于 objectData 的单独查询,您有几个选择。您可以强制客户端在查询之前检查您是否有 objectData:

if (myClass.hasObjectData()) {
    ObjectData data = myClass.getObjectData();
}

或者您可以 return 指针。如果客户端不需要拥有 ObjectData 你可以只 return 一个原始指针。如果客户端需要拥有 ObjectData 我不认为在堆上分配和 return 使用智能指针有什么不好的:

std::unique_ptr<ObjectData> data = myClass.getObjectData();
if (data) {
    // do something with data...
}

或者以类似的方式,您可以使用 Boost.Optional

如果没有额外的对象数据,您也可以考虑 Null Object pattern 和 return 一个 NullObjectData 对象。