2015-10-07 65 views
0

我期待找到使用这种代码安全地以正确的方式返回时,存在对象:希望在何处检查是否从函数与循环

renderer->renderEntity(entityManager->getEntity("player")); 

Entity EntityManager::getEntity(string entityName) 
{ 
    for (int index = 0; index < entityVector.size(); ++index) 
    { 
     if (entityVector[index].getName() == entityName) 
     { 
      return entityVector[index]; 
     } 
    } 
} 

从容器中得到内的对象一个类的实例,并且想要检查它是否存在,所以你没有对不存在的对象进行调用。

我知道我可以改变的呼吁:

if (entityManager->getEntity("player" != nullptr) 
{ 
    renderer->renderEntity("player"); 
} 

我想避免双重调用来检查对象存在。我想这可能是一个比语法问题更多的设计。我可以在包含for循环的getEntity()函数中构建错误检查吗?我不确定,因为返回值是实体,所以必须返回一个实体对象。 (如果它是一个指针,则相同,这不是我的项目中的代码,只是一个类似的例子)。

+1

常见的是如何认为的那个实体名称将不存在?如果这种情况很少发生,你可以抛出异常。另一种选择是采用标准库方法,并将一个迭代器返回给元素,如果它不存在,则返回'entityVector.end()'。 – TartanLlama

+0

如果实体不存在,您的方法应该返回什么? –

+1

我会建议使用'std :: map' – Paranaix

回答

0

这应该有所帮助。一个简单的空对象模式

https://en.wikipedia.org/wiki/Null_Object_pattern

class Entity 
{ 
public: 
    virtual void render() 
    { 
     // do somthing 
    } 
}; 

class EmptyEntity final : public Entity 
{ 
public: 
    void render() override 
    { 
     //Do nothing or print log 
    } 
} static g_EmptyEntity; 

Entity EntityManager::getEntity(string entityName) 
{ 
    for (int index = 0; index < entityVector.size(); ++index) 
    { 
     if (entityVector[index].getName() == entityName) 
     { 
      return entityVector[index]; 
     } 
    } 
    return g_EmptyEntity; 
} 
+0

这几乎正是我想要的,覆盖任何功能都没有发生在我身上。真的很好的解决方案,我认为会有一个设计模式!谢谢。 – martingrant

+0

当你按价值回报时,你得到了对象切片。 – Jarod42

+0

是Jarod42。但由于提问者没有更多的细节,所以我不能包含所有的细节。实体和EntityManager :: getEntity(string entityName)可以帮助 –

0

如果您可以更改返回类型:make getEntity()返回一个指针,如果该对象不存在,则返回NULL。

或者,如@ TartanLlama建议您可以返回一个迭代器。

其他选项(只在某些情况下才有效):您的方法可以记住上次调用该方法的entityName以及生成的索引。输入时首先检查当前输入是否等于先前的输入:在这种情况下,您将返回存储的索引而不再搜索。

+0

这会工作,但我希望能够在使用它之前不必检查对象是否为NULL,所以我没有太多的if语句堵塞代码。 你的第二点是好的。我喜欢这一点,如果你正在寻找一个你最近发现的物体,就跳过搜索。绝对是我可以用来提高效率的东西,谢谢! – martingrant

+0

检查对象是否为NULL与检查元素是否存在相同,它们是相同的情况。我不明白它如何帮助,除非这个方法findEntityByName()生成元素,如果它不存在。 –

0

返回指针将是简单/更清晰:

Entity* EntityManager::findEntityByName(const std::string& entityName) 
{ 
    const auto it = std::find_if(entityVector.begin(), entityVector.end(), 
           [&](const auto& e) { 
             return e.getName() == entityName; 
           }); 
    if (it == entityVector.end()) { // Not found. 
     return nullptr; 
    } 
    return std::addressof(*it); 
} 

然后

auto* entity = entityManager->findEntityByName("player"); 
if (entity != nullptr) 
{ 
    renderer->renderEntity(entity); 
} 
+0

我希望得到的是在我使用它之前不需要检查对象是否为空的情况。但是在你的回答中有一些非常好的东西,我不知道std :: find_if()和std :: addressof()。谢谢,他们将在未来对我有用! – martingrant