C++;并返回一个空值-在Java中工作的东西不';t在C+中工作+; 所以我有一个相当混乱的转换到爪哇+ C++的C++。尽管我觉得我理解了大部分的基础知识,但在我的理解中还是有一些巨大的漏洞 例如,考虑以下函数: Fruit& FruitBasket::getFruitByName(std::string fruitName) { std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName); if(it != _fruitInTheBascit.end()) { return (*it).second; } else { //I would so love to just return null here } } 水果& 水果篮::GetFroothByName(标准::字符串FroothName) { std::map::iterator it=\u fruitInBascit.find(fruitName); if(it!=\u foultinBascit.end()) { 返回(*it); } 其他的 { //我很想在这里返回空值 } }
其中,C++;并返回一个空值-在Java中工作的东西不';t在C+中工作+; 所以我有一个相当混乱的转换到爪哇+ C++的C++。尽管我觉得我理解了大部分的基础知识,但在我的理解中还是有一些巨大的漏洞 例如,考虑以下函数: Fruit& FruitBasket::getFruitByName(std::string fruitName) { std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName); if(it != _fruitInTheBascit.end()) { return (*it).second; } else { //I would so love to just return null here } } 水果& 水果篮::GetFroothByName(标准::字符串FroothName) { std::map::iterator it=\u fruitInBascit.find(fruitName); if(it!=\u foultinBascit.end()) { 返回(*it); } 其他的 { //我很想在这里返回空值 } },c++,null,C++,Null,其中,\u foultsinthebascit是一个std::map。如果我查询getFruitByName(“金橘”)你知道它不会在那里-谁吃金橘?但我不想我的程序崩溃。在这些情况下应该怎么做 请告诉我我还没有确定的其他愚蠢之处。 < P>如果你需要NULL,你可以返回一个指针而不是引用。 < P>没有作为C++引用的空引用,所以如果函数返回引用,你就不能返回null。您有几个选择: 更改返回类型,使函数返回指针;如果找不到元素,则返回null 保留引用返回类型,但具有某种“sentinel”
\u foultsinthebascit
是一个std::map
。如果我查询getFruitByName(“金橘”)
你知道它不会在那里-谁吃金橘?但我不想我的程序崩溃。在这些情况下应该怎么做
请告诉我我还没有确定的其他愚蠢之处。
< P>如果你需要NULL,你可以返回一个指针而不是引用。 < P>没有作为C++引用的空引用,所以如果函数返回引用,你就不能返回null。您有几个选择:FruitNotFoundException
)举一个“不太可能”失败的例子:在我当前的项目中,我有一个管理对象的类,有一个返回对象是否存在的函数
is\u object\u present
,还有一个返回对象的函数get\u object
。我总是希望调用方在调用get\u object
之前通过调用is\u object\u present
来验证对象的存在,因此在这种情况下失败的可能性很小。这不起作用的原因是因为您的函数返回了一个引用。引用必须始终是实际实例。java不是C++。
解决此问题的一种方法是更改函数以返回指针,该指针的工作方式更像java使用的引用。在这种情况下,您可以返回null代码>
Fruit*
FruitBasket::getFruitByName(std::string fruitName)
{
std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName);
if(it != _fruitInTheBascit.end())
{
return &(*it).second;
}
else
{
return NULL;
}
}
水果*
水果篮::GetFroothByName(标准::字符串FroothName)
{
std::map::iterator it=\u fruitInBascit.find(fruitName);
if(it!=\u foultinBascit.end())
{
返回&(*it)。第二;
}
其他的
{
返回NULL;
}
}
如果出于某种原因希望避免这样做,可以定义一个sentinel对象并返回它。像这样的
Fruit NullFruit;
Fruit&
FruitBasket::getFruitByName(std::string fruitName)
{
std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName);
if(it != _fruitInTheBascit.end())
{
return (*it).second;
}
else
{
return NullFruit;
}
}
水果和水果;
果&
水果篮::GetFroothByName(标准::字符串FroothName)
{
std::map::iterator it=\u fruitInBascit.find(fruitName);
if(it!=\u foultinBascit.end())
{
返回(*it);
}
其他的
{
还果;
}
}
另一个选择是根本不返回。提出例外
class NullFruitException: public std::exception {};
Fruit&
FruitBasket::getFruitByName(std::string fruitName)
{
std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName);
if(it != _fruitInTheBascit.end())
{
return (*it).second;
}
else
{
throw NullFruitException;
}
}
类异常:公共std::异常{};
果&
水果篮::GetFroothByName(标准::字符串FroothName)
{
std::map::iterator it=\u fruitInBascit.find(fruitName);
if(it!=\u foultinBascit.end())
{
返回(*it);
}
其他的
{
抛出一个异常;
}
}
引用不能为空。它们在异常情况下工作得最好——您可以抛出错误代码,而不是返回错误代码
或者,您可以使用带有错误代码返回值的“out”参数:
bool FruitBasket::getFruitByName(const std::string& fruitName, Fruit& fruit)
{
std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName);
if(it != _fruitInTheBascit.end())
{
fruit = (*it).second;
return true;
}
else
{
return false;
}
}
我在C++系里有点生疏了。但是有没有可能用水果来代替水果&
如果进行了此更改,则可以说“returnnull;”(或returnnull,或return0…无论C++的语法是什么) 好的。有很多解决方案。
詹姆斯·麦克内利斯已经涵盖了所有显而易见的问题。
就个人而言,我更喜欢他的解决方案(1),但缺少很多细节
另一种方法(我把它作为一种方法扔掉)是创建一个水果引用类型,它知道对象是否有效。然后,您可以从getFroothByName()方法返回:
基本上,它与返回指针相同;但是没有与指针关联的所有权符号,因此很难判断是否应该删除指针。通过使用FROUT引用类型,您不会公开指针,因此不会导致所有权混淆
class FruitReference
{
public:
FruitReference() // When nothing was found use this.
:data(NULL)
{}
FruitReference(Fruit& fruit) // When you fidn data.
:data(&fruit)
{}
bool isValid() const { return data != NULL;}
Fruit& getRef() const { return *data; }
private:
Fruit* data; //(not owned)
};
FruitReference const& FruitBasket::getFruitByName(std::string fruitName)
{
std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName);
if(it != _fruitInTheBascit.end())
{
return FruitReference((*it).second);
}
else
{
return FruitReference();
}
}
类引用
{
公众:
FruitReference()//未找到任何内容时,请使用此选项。
:数据(空)
{}
水果参考(水果和水果)//当您fidn数据时。
:数据(&F)
{}
bool isValid()常量{返回数据!=NULL;}
水果&getRef()常量{return*data;}
私人:
水果*数据;//(非自有)
};
水果引用常量和水果篮::GetFroothByName(标准::字符串水果名)
{
std::map::iterator it=\u fruitInBascit.find(fruitName);
if(it!=\u foultinBascit.end())
{
返回引用((*it.second);
}
其他的
{
返回引用();
}
}
我确信boost也有类似的东西,但我在20秒的搜索中找不到。詹姆斯·麦克内利斯的答案恰到好处。然而,我要指出的是,您应该将C++的指针视为类似于Java的引用,而不是将C++的引用视为类似于Java的引用。如果您试图返回一个不能为null的基元类型,那么您在这种情况下所做的与在Java中所做的类似。在这一点上,你基本上是按照詹姆斯的建议做的
class FruitReference
{
public:
FruitReference() // When nothing was found use this.
:data(NULL)
{}
FruitReference(Fruit& fruit) // When you fidn data.
:data(&fruit)
{}
bool isValid() const { return data != NULL;}
Fruit& getRef() const { return *data; }
private:
Fruit* data; //(not owned)
};
FruitReference const& FruitBasket::getFruitByName(std::string fruitName)
{
std::map<std::string,Fruit>::iterator it = _fruitInTheBascit.find(fruitName);
if(it != _fruitInTheBascit.end())
{
return FruitReference((*it).second);
}
else
{
return FruitReference();
}
}