2011-01-25 82 views
2

我有一個堆棧容器類,我想創建各種類型的堆棧實例。所以我這樣做:C++模板問題:轉換爲空

template <typename T> 
class MyStack 
{ 
. 
. 
    T Pop() 
    { 
     if(!IsEmpty()) 
     { 
     return data[top--]; 
     } 
     else 
     { 
     return NULL; // I got error here 
     } 
. 
. 
} 

當我嘗試使用堆棧是這樣的:

MyStack<GraphNode> blacks; 
GraphNode t = blacks.Pop(); 

我得到這個錯誤:

conversion from ‘int’ to non-scalar type ‘GraphNode’ requested 

但是當我使用指針類型一樣Stack<GraphNode*>有沒問題。我知道NULL0,我明白爲什麼會發生錯誤...什麼是優雅的方式來告訴程序,沒有數據要返回而不更改代碼?我應該添加類似隱式類型轉換操作符類嗎?怎麼樣?

注:我不使用STL

+0

可能重複的[如何從模板類中的方法返回NULL](http://stackoverflow.com/questions/1392869/how-to-return-null-from-a-method-in-a-模板級) – Suma 2011-01-25 20:43:17

+0

+1重複,但很難保證downvote。這是一個很好的問題。 – Skurmedel 2011-01-25 20:45:04

+0

downvote是嘗試一些設計不好的東西,應該完全避免 - 「不用更改代碼?」。沒有必要被迷戀 - downvote只是一個downvote,一個個人的觀點,它不是「從地球表面擦拭他」。 – Suma 2011-01-25 20:47:58

回答

6

通過按值返回T,您的功能合同是您返回一個值。這兩種方法是更改​​函數的合同(例如,改爲返回T*),或者拋出異常而無法返回。

就我個人而言,我認爲在這種情況下拋出異常是可以接受和適當的。返回一個指針,或者談論覆蓋並返回一個布爾成功值的引用都不是那麼幹淨的解決方案。

特別是如果您提供公開的IsEmpty()方法,沒有理由選擇不太乾淨的解決方案。不想處理異常的客戶端可以使用IsEmpty來避免接收到等同於斷言的異常。

3

的規範彈出函數返回void,這個確切原因。另外,你沒有調用Bad的數據析構函數[top]。

如有疑問,請檢查STL

5

STL std::stack將此功能拆分爲top(),它返回最後一個元素的引用,pop()。如果您使用其中的任何一種,並且堆棧已經爲空(即如果empty() == true),則行爲是簡單的未定義的。這聽起來不是一個壞的方法。

3

如果您還沒有閱讀GoTW #8,現在應該這樣做。它完全致力於手頭的問題 - 如何設計堆棧。其最基本的一點是,您目前使用的設計pop不能將設爲異常安全。

它給手頭上的問題(不一定是一個好......)答案是返回一個缺省構造■如果堆棧是空的:

T Pop() 
{ 
    if(!IsEmpty()) 
    { 
    return data[top--]; 
    } 
    else 
    { 
    return T(); // No more error 
    } 
} 

這樣做的問題是,在大多數的情況下,試圖彈出一個空堆棧表明一個邏輯錯誤,並且不應該被允許繼續進行。您可以在使用assert或拋出異常之間進行無休止的辯論,但很少有可以返回的值,這非常有用(可能的例外是在處理F.P.數字時返回NaN)。