2010-04-14 84 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. 
} 
相關問題