我对C ++很陌生,所以在我学习的时候,我倾向于设计很多Java主义。无论如何,在Java中,如果我的类具有“搜索”方法,该方法将从匹配特定参数的T
返回对象Collection< T >
,我将返回该对象,如果找不到该对象在集合中,我会返回null
。然后在我的调用函数中,我只需检查if(tResult != 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;
}
如何更改它以便我可以提供这种标记?
答案 0 :(得分:61)
在C ++中,引用不能为null。如果要在没有找到任何内容的情况下选择返回null,则需要返回一个指针,而不是引用:
Attr *getAttribute(const string& attribute_name) const {
//search collection
//if found at i
return &attributes[i];
//if not found
return nullptr;
}
否则,如果您坚持通过引用返回,那么如果找不到该属性,则应该抛出异常。
(顺便说一下,我有点担心你的方法是const
并返回非const
属性。出于哲学原因,我建议你回复const Attr *
。如果您还想修改此属性,则可以使用非const
方法重载,同时返回非const
属性。)
答案 1 :(得分:52)
这里有几个可能的答案。您想要返回可能存在的内容。以下是一些选项,从我最喜欢的到最喜欢的:
以引用方式返回,并且异常无法找到信号。
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<Attr&> getAttribute(const string& attribute_name) const
{
//search collection
//if found at i
return attributes[i];
//if not found
return boost::optional<Attr&>();
}
boost :: optional表示这里到底发生了什么,并且有简单的方法来检查是否找到了这样的属性。
附注:std :: optional最近被投票到C ++ 17,所以这将是不久的将来的“标准”事情。
答案 2 :(得分: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;
答案 3 :(得分:3)
如果您想要NULL
返回值,则需要使用指针而不是引用。
参考文献本身不能是NULL
。
(请注意以后的评论海报:是的,如果真的真的尝试,你可以将引用的地址设为NULL。)
See my answer here for a list of differences between references and pointers
答案 4 :(得分: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;
}
上面的函数必须针对键'token'找到Operator,如果找到它返回true的那个并将值赋给参数Operator&amp;同前。
此例程的调用者代码如下所示
Operator opr;
if (OperatorList::tryGetOperator(strOperator, opr))
{
//Do something here if true is returned.
}
答案 5 :(得分:1)
此处无法返回NULL的原因是您已将返回类型声明为Attr&
。尾部&
使返回值成为“引用”,它基本上是指向现有对象的保证不为空的指针。如果您希望能够返回null,请将Attr&
更改为Attr*
。
答案 6 :(得分:0)
您无法返回NULL
,因为该函数的返回类型是对象reference
而不是pointer
。
答案 7 :(得分:0)
在这种情况下还可以考虑另一种选择 - 取决于您的设计。您可以使用函数的参数返回值并使函数返回 bool
,例如
bool getAttribute(const string& attribute_name, Attr& returnAttr) const {
//search collection
//if found at i
returnAttr = attributes[i];
return true;
//if not found
return false;
}
答案 8 :(得分:-4)
你可以试试这个:
return &Type();