如何处理不保证返回任何内容的函数
How to handle a function that is not guaranteed to return anything?
我有一个类,用于存储和管理包含许多对象的向量。
我发现自己正在编写许多类似于以下内容的函数:
Object* ObjectManager::getObject(std::string name){
for(auto it = object_store.begin(); it != object_store.end(); ++it){
if(it->isCalled(name))
return &(*it)
}
return nullptr;
}
我想我宁愿通过引用返回,因为在这里调用者必须记住检查 null!有没有办法改变我的设计以更好地处理这个问题?
您的替代方案概述如下
将 API 更改为以下内容
object_manager.execute_if_has_object("something", [](auto& object) {
use_object(object);
});
此 API 更易于使用,完美地传达了意图,并从用户的脑海中消除了错误处理、返回类型等的思维过程
引发异常。
Object& ObjectManager::getObject(const std::string& name){
for(auto& object : object_store){
if(object.isCalled(name))
return object;
}
// throw an exception
throw std::runtime_error{"Object not found"};
}
返回一个布尔值,通过引用传递Object
并获取副本
bool ObjectManager::getObject(const std::string& name, Object& object_out){
for(auto& object : object_store){
if(object.isCalled(name)) {
object_out = object;
return true;
}
}
return false;
}
让用户进行查找
auto iter = std::find(object_store.begin(), object_store.end(), [&name](auto& element) {
return element.isCalled(name);
}
if (iter != object_store.end()) { ... }
也
- 通过常量引用传递该字符串。 当 C++17 可用时,更改对
std::string_view
的常量引用 - 在这种情况下使用基于范围的 for 循环,它们是您正在执行的操作的更具可读性的替代方案
看看STL的设计(例如 find
函数(,返回您刚刚搜索的迭代器并返回.end()
否则一点也不坏。
auto ObjectManager::getObject(std::string name){
for(auto it = object_store.begin(); it != object_store.end(); ++it){
if(it->isCalled(name))
return it;
}
return object_store.end();
}
更多:当然object_store.end()
可能无法从类外访问,但这不是借口,因为您可以这样做(请注意更流畅的代码(
auto ObjectManager::getObject(std::string name){
auto it = object_store.begin();
while(not it->isCalled(name)) ++it;
return it;
}
auto ObjectManager::nullObject(){return object_store.end();}
代码越少越好。你可以像这样使用它:
auto result = *om.getObject("pizza"); // search, not check (if you know what you are doing)
或
auto it = om.getObject("pizza");
if(it != om.nullObject() ){ ... do something with *it... }
或
auto it = om.getObject("pizza");
if(it != om.nullObject() ){ ... do something with *it... }
else throw java_like_ridiculous_error("I can't find the object, the universe will collapse and it will jump to another plane of existence");
当然,在这一点上,最好调用函数findOject
和noposObject
,并质疑为什么不在object_store
容器上使用直接std::find
。
我认为您已经正确处理了返回值,并且您当前的解决方案是最佳的。
事实是,您无法避免检查某些内容以发现查找操作是否成功。如果您抛出异常,那么您try{}catch{}
就是您的支票。此外,当找不到项目是合法结果时,不应使用exception
。如果返回bool
并使用 out 参数,则使执行相同工作的情况更加复杂。与返回迭代器相同。std::optional
返回值。
因此,IMO 您无法在返回指针后进行改进,您只能使相同的工作更加复杂。
异常或可选的替代方案是实现一个"Null 对象" - 它可以用作常规对象,但"什么都不做"。根据具体情况,有时它可以按原样使用,不需要(明确(检查 - 特别是在忽略"未找到"情况是可以接受的情况下。
(null 对象可以是静态全局,因此也可以返回对它的引用(
即使需要检查,也可以实现isNull()
方法,该方法为空对象返回 true,为有效对象返回 false(或者可以有isValid()
方法等(。
例:
class Object {
public:
virtual void doSomething();
};
class NullObject: public Object {
public:
virtual void doSomething() {
// doing nothing - ignoring the null object
}
};
class ObjectManager {
public:
Object& getObject(const std::string& name);
private:
static NullObject s_nullObject;
};
Object& ObjectManager::getObject(const std::string& name){
for(auto it = object_store.begin(); it != object_store.end(); ++it){
if(it->isCalled(name))
return *it;
}
return s_nullObject;
}
ObjectManager mgr;
Object& obj = mgr.getObject(name);
obj.doSomething(); // does nothing if the object is NullObject
// (without having to check!)
- 模板化接口 - 创建一个泛型模板类以返回任何容器
- 这是使用回溯的 nqueen 问题,但我使用了动态 2d 数组,我的程序编译良好,但不返回任何输出
- C++ - 声明指向返回任何类型并获取任意数量参数的函数的指针
- 类和构造函数中的函数根本不起作用,并且不返回任何错误
- 为什么套接字中的 recv() 函数不返回任何内容?
- 是否有任何内置的哈希图函数来处理 c++ 中的值输入?
- C++如何使虚拟函数返回任何类型的指针
- 返回类型为struct的函数每次调用时都不返回任何内容
- 此程序不返回任何内容
- 是否有任何内置函数可以检查给定的两个数字在给定整数数组中的顺序是否相同?
- std::ifstream.read() 不会向我的缓冲区返回任何内容
- 为什么即使输入相等,v3 也不会返回任何内容
- glGetBufferSubData() 不返回任何数据?
- stbi_load() 不返回任何内容,但不返回 null
- C++ 中是否有任何内置阶乘函数?
- 如何处理不保证返回任何内容的函数
- C++递归不返回任何内容
- MySQL++ 不返回任何内容
- stbi_load不返回任何值
- 是否有任何内置函数可以告诉编译器分支是否可预测