2015-05-01 68 views
1

我想實現二叉搜索樹。我有私人和公共get()方法。對於private get(),我返回Node對象,或者如果找不到該節點,則返回異常。對於public get()我返回Node對象的值,即std :: string或捕獲該異常。用戶只能調用public get(),我試圖避免讓用戶使用異常。這就是爲什麼我在public get()中捕獲異常而不是將其重新推送給用戶的原因。我的問題是,當public get()捕獲異常時如何終止函數,因爲我的返回類型是std :: string。我試圖返回-1或std :: terminate(),但他們沒有工作。有沒有辦法處理這個問題,或者我必須重新拋出異常或更改我的返回類型?謝謝。這是我的代碼。發生異常時如何返回非void函數,而不使用異常? C++

// public 
std::string BST::get(int key) { 
    Node *node; 
    try { 
    node = get(key, my_root); 
    } 
    catch (const std::out_of_range& oor) { 
    std::cout << oor.what() << std::endl; 
    // How to let the function terminate here? 
    }  
    return node->value; 
} 

//private 
Node* BST::get(int key, Node* root) { 
    if (root == NULL) { 
     throw std::out_of_range("Cannot find."); 
    } 
    if (key < root->key) { 
     return get_node(key, root->left); 
    } else if (key > root->key) { 
     return get_node(key, root->right); 
    } else { 
     return root; 
    } 
} 
+3

您可以決定如何表示「該項目不存在」。例如,您可以使用空字符串。 –

+0

或者,表示可空對象的一種方法是使用指針,但如果你走這條路線,則必須更加註意內存管理。 – huu

+0

這聽起來像是你問到如何在函數結束之前「離開」一個函數。那是對的嗎? –

回答

0

您需要保留一個可能的返回值來指示錯誤。

例如,返回的std::string可能包含空字符串("") - 假設沒有任何錯誤發生時可以返回空字符串。

如果返回一個指針,返回NULL是很常見的指示錯誤。

如果返回int,請選擇一些指示錯誤的值(如果只有非零結果,則爲int的最大值,常見選項爲零)。

0

通常情況下,它將是一個API協議來返回一個特定的值。通常它會像一個空白字符串,但如果一個空字符串是一個有效的返回它可能是其他的一些其他值不會出現。

std::string BST::get(int key) { 
    Node *node; 
    try { 
     node = get(key, my_root); 
    } 
    catch (const std::out_of_range& oor) { 
     return std::string("0xDEADBEEF"); 
    }  
    return node->value; 
} 

否則,你可以使用C風格的迴歸,在那裏你返回一個整數,無論​​工作與否,並採取其他參數,如果它發現與輸出中填補進去。 (不是很像C++,我知道,但它工作!)

3

考慮用布爾值和字符串返回一對。

std::pair<bool, std::string> BST::get(int key) { 
    Node *node; 
    try { 
     node = get(key, my_root); 
    } 
    catch (const std::out_of_range& oor) { 
     std::cout << oor.what() << std::endl; 
     // How to let the function terminate here? 
     return std::make_pair(false, ""); 
    }  
    return std::make_pair(true, node->value); 
} 

使用魔術值表示缺少值的問題是始終有一個值將被實際使用的機會。

+0

有趣。我從來沒有想過要退回一對。那個布爾值是做什麼的?就像,如果用戶檢測到布爾是「假」,那麼它選擇不打印任何東西。如果bool是「真」,那麼它會打印字符串? – ZigZagZebra

+0

布爾值指示是否找到密鑰。是的,你打印的例子是呼叫者可能做的一件事。 –

+0

我明白了。謝謝! – ZigZagZebra

0

我的問題是,如何終止該功能時,公共的get()捕捉異常

一個return聲明是在你的函數的任何位置有效。

它表示控制應該返回到調用它的函數。

std::string BST::get(int key) { 
    Node *node; 
    try { 
    node = get(key, my_root); 
    } 

    catch (const std::out_of_range& oor) { 
    std::cout << oor.what() << std::endl; 
    return std::string(); // I choose the empty string to mean "key not found" 
    } 
    return node->value; 
} 
0

最好的自我註釋的解決方案,您的問題是:

  1. 返回專用類模板上,可以交替舉辦相關的錯誤信息,您的預期收益類型。因此,該課程將被命名爲例如template<class T> class Expected { /* ... /* }。要深入瞭解此選項,請檢查Alexandresu的話題:Systematic Error Handling in C++。你也可以找到一個建議,將其納入升壓:Boost.Expected Google summer of code proposal。或進入std:A proposal to add a utility class to represent expected monad。 由於所有這些僅僅是建議,並且由於我發現這種錯誤處理非常針對項目,所以您當然需要沿着參考行推出自己的類。

    1. 使用boost::optional<std::string>。事實上的標準回答你的問題。在出乎意料的情況下,它沒有提供錯誤信息的空間,但與您的用例無關。
0

有兩種基本方法是:

  1. 你保留一個特殊值的信號錯誤條件。

  2. 您使用側通道傳達錯誤情況。下面是我想到的可能的旁通道的完整列表:

    1. 您返回一個指向您的字符串的指針。這允許您在發生錯誤時返回nullptr(指針值是旁路通道)。

    2. 您返回一個包含預期返回值和可能的錯誤條件的對象。

    3. 您可以使用一個參考/指針參數作爲輔助通道。

      std::string get(int key, int* error = nullptr); 
      

      如果error參數不是null,您只需設置*error發出錯誤信號時是否發生:例如,你可以宣佈你的公共的getter。如果發生錯誤,您還會返回空字符串(與error是否爲空無關)。

它們都有一定的優勢,而一些缺點。這裏有一些更重要的:

  • 特殊值限制了可能的用途。除非您確切知道用​​戶需要(不太可能),否則使用空字符串將禁止您的課程的某些用途。部分用戶需要存儲空字符串。

  • 返回std::pair<>或類似使用情況很笨拙。返回的對象需要使用新變量顯式內省。

  • 同樣,錯誤參數方法要求在調用函數之前聲明錯誤參數的變量。但是,它也允許用戶通過一個nullptr,如果它們滿足您錯誤返回的值。 I. e。需要將空字符串作爲值的用戶將使用錯誤參數,不需要區分空字符串和未設置值的用戶不需要做任何特殊處理。