2010-04-14 85 views
83

我对C++很新颖,所以我倾向于在学习时用很多Java-ims进行设计。无论如何,在Java中,如果我有一个'搜索'方法的类将返回匹配一个特定参数的Collection< T >对象T,我会返回该对象,如果在该集合中找不到对象,我会返回null 。然后在我的调用函数,我只是检查if(tResult != null) { ... }如果搜索结果未找到,则返回“NULL”对象

在C++中,我发现如果对象不存在,我不能返回null值。我只想返回一个类型为T的“指示符”,通知调用函数没有找到对象。我不想抛出异常,因为这不是一个真正的例外情况。

这是我的代码看起来像现在:

class Node { 
    Attr& getAttribute(const string& attribute_name) const { 
     //search collection 
     //if found at i 
      return attributes[i]; 
     //if not found 
      return NULL; // what should this be? 
    } 

private: 
    vector<Attr> attributes; 
} 

我怎样才能改变它,所以我可以给那种标记?

+5

异常和NULL并不总是唯一的解决方案。你经常可以选择一个返回值来表示找不到:例如,如果没有元素匹配,'std :: find(first,last,value)'返回'last'。 – Cascabel 2010-04-14 16:47:39

回答

57

在C++中,引用不能为空。如果你想有选择地返回NULL如果没有找到,你需要返回一个指针,而不是一个参考:

Attr *getAttribute(const string& attribute_name) const { 
    //search collection 
    //if found at i 
     return &attributes[i]; 
    //if not found 
     return nullptr; 
} 

否则,如果你坚持通过引用返回,那么你应该抛出一个异常,如果该属性ISN没有发现。

(顺便说一下,我有点担心你的方法是const并返回一个非const属性。对于哲学的原因,我建议恢复const Attr *。如果你也可能要修改此属性,可以用非const方法返回一个非const属性以及过载。)

+2

谢谢。顺便说一句,这是设计这样一个例程的可接受的方式吗? – aduric 2010-04-14 17:00:56

+5

@aduric:是的。参考意味着结果必须存在。指针意味着结果可能不存在。 – Bill 2010-04-14 17:15:48

+6

只是好奇,我们现在应该返回'nullptr'而不是'NULL'吗? – 8090PZ 2014-11-09 19:12:28

0

你无法返回NULL,因为该函数的返回类型是一个对象reference而不是pointer

1

你不能在这里返回NULL的原因是因为你已经声明你的返回类型为Attr&。尾部&使返回值成为“引用”,它基本上是一个保证不是空指针的现有对象。如果您希望能够返回空值,请将Attr&更改为Attr*

50

这里有几种可能的答案。你想要返回可能存在的东西。这里有一些选项,从我的最不喜欢到最优选:

  • 返回通过引用,信号找不到例外。

    Attr& getAttribute(const string& attribute_name) const 
    { 
        //search collection 
        //if found at i 
         return attributes[i]; 
        //if not found 
         throw no_such_attribute_error; 
    }

这可能是因为没有找到属性是执行正常的一部分,因此不是很出色的。处理这将是嘈杂。无法返回空值,因为它的未定义行为具有空引用。

  • 回到依指针

    Attr* getAttribute(const string& attribute_name) const 
    { 
        //search collection 
        //if found at i 
         return &attributes[i]; 
        //if not found 
         return nullptr; 
    }

人们很容易忘记检查从的getAttribute结果是否将是一个非NULL指针,是错误的来源容易。

  • 使用Boost.Optional

    boost::optional<Attr&> getAttribute(const string& attribute_name) const 
    { 
        //search collection 
        //if found at i 
         return attributes[i]; 
        //if not found 
         return boost::optional<Attr&>(); 
    }

一个boost ::可选表示到底是怎么回事就在这里,并具有检测这样的属性是否找到简单的方法。


附注:std :: optional最近被投票到C++ 17中,所以这将成为不久的将来的“标准”事情。

+0

+1我只是提到boost ::可选第一,并且只是简单地提及其他选择。 – 2010-04-14 17:02:55

+0

雅我看到boost ::可选在某处提到,但我认为它需要太多的开销。如果使用它是解决这些问题的最佳方法,我将开始使用它。 – aduric 2010-04-14 17:09:37

+0

'boost :: optional'不涉及太多开销(没有动态分配),这就是为什么它非常棒。使用它与多态值需要包装引用或指针。 – 2010-04-14 18:09:43

22

您可以轻松创建一个表示NULL返回值的静态对象。

class Attr; 
extern Attr AttrNull; 

class Node { 
.... 

Attr& getAttribute(const string& attribute_name) const { 
    //search collection 
    //if found at i 
     return attributes[i]; 
    //if not found 
     return AttrNull; 
} 

bool IsNull(const Attr& test) const { 
    return &test == &AttrNull; 
} 

private: 
    vector<Attr> attributes; 
}; 

而且在源文件中的某个地方:

static Attr AttrNull; 
+0

NodeNull不应该是Attr类型的吗? – aduric 2010-04-14 17:12:43

+0

好点,我会修复这个例子。 – 2010-04-14 17:19:21

-4

你可以试试这个:

return &Type(); 
+6

尽管此代码片段可能会解决问题,但[包括解释](http://meta.stackexchange.com/questions/114762/explaining-entirely-基于代码的答案)确实有助于提高您的质量帖子。请记住,您将来会为读者回答问题,而这些人可能不知道您的代码建议的原因。 – NathanOliver 2015-12-14 21:10:22

+0

这可能会返回对方法堆栈上的对象的死引用,不是吗? – mpromonet 2015-12-16 21:37:25

+0

正好。 lllllll – Created 2015-12-17 21:32:48

2

当你想通了,你不能做到这一点,你在Java中已经做了(或C#)。这里是另一个建议,你可以将对象的引用作为参数传递并返回bool值。如果在集合中找到结果,则可以将其分配给正在传递的引用,并返回“true”,否则返回“false”。请考虑这个代码。

typedef std::map<string, Operator> OPERATORS_MAP; 

bool OperatorList::tryGetOperator(string token, Operator& op) 
{ 
    bool val = false; 

    OPERATORS_MAP::iterator it = m_operators.find(token); 
    if (it != m_operators.end()) 
    { 
     op = it->second; 
     val = true; 
    } 
    return val; 
} 

功能上面已经找到操作员对键“令牌”,如果它发现它返回true一个并分配值参数operator &运算。

这个程序调用者的代码如下所示

Operator opr; 
if (OperatorList::tryGetOperator(strOperator, opr)) 
{ 
    //Do something here if true is returned. 
} 
相关问题