2011-01-25 9 views
2

私はStackコンテナクラスを持っていて、さまざまなタイプのスタックのインスタンスを作成したいと思います。私はこのようなスタックを使用しようとするとC++のテンプレート問題:nullに変換

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

+0

+1重複していますが、ダウンボントはほとんどありません。それはよく定式化された質問です。 – Skurmedel

+0

downvoteは悪いデザインのものを試してみたもので、 "コードを変更せずに"完全に避けるべきです。執着する必要はありません - ダウンボートは単にダウンボォートです、個人的な意見ではなく、 "地球の顔から彼を拭く"ではありません。 – Suma

答えて

6

Tを値で返すと、関数の契約によって、に戻ります。 2つの選択肢は、機能の契約を変更するか(代わりにT*を返すなど)、例外をスローして返さないようにすることです。

個人的には、この場合は例外をスローすることが許容され適切であると私は考える。ポインタを返すか、またはブール値成功値を上書きして返すための参照を話すことは、どちらもクリーンなソリューションではありません。

特に公共のIsEmpty()メソッドを提供する場合は、あまりクリーンなソリューションを選択する理由はありません。例外を処理したくないクライアントは、IsEmptyを使用して、例外の受信を避けることができます。これは、アサートの同等物になります。

+0

また、空のスタックでPopを呼び出すことがプログラマーのエラー(契約に対して使用されるインターフェース)と考えられる場合は、assertの使用を検討するとよいでしょう。 – Suma

+0

@Suma:答えを更新しているようにコメントしました。私は同意する、それは有効なアプローチだ。 –

+0

ありがとうございます。私はポインタを返すつもりです。私は例外を使用しないでください:-) –

3

正規のポップ機能は、まさにこの理由のためにvoidを返すを使用していませんよ。また、データのデストラクタを呼び出さなかった[上]、Bad™です。

疑わしい場合はSTLにチェックを入れてください。

+0

'data'がスタック上の静的なサイズの配列でなければ、そこには大量のメモリリークがあります。 – user470379

+1

いいえ、voidを返す理由は、可能な限り不要なコピーを防ぐためです(TC++ PLの古い人Stroustrupによる)。使用可能な要素がない場合、 'back'は静かに失敗するので、値で返さない理由は* no *です。 –

5

STL std::stackは、この機能をtop()に分割し、最後の要素への参照を返します。pop()。これらのいずれかを使用してスタックが既に空の場合(つまり、empty() == trueの場合)、動作は未定義です。これは悪いアプローチのようには聞こえません。

3

GoTW #8をお読みになっていない場合は、今すぐお試しください。これは手元の問題、すなわちスタックを設計する方法に完全に専念しています。その最も基本的なポイントの1つは、popのために現在使用しているデザインはを例外的に安全にすることができないということです。

それは手元の質問に与える答え(必ずしも良いもの...)スタックが空の場合、デフォルトで構築Tを返すことです:

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

これに問題があることですでほとんどの場合、空のスタックをポップしようとすると論理エラーが発生するため、何も進めないでください。あなたはassertの使用を無限に議論することも、例外を投げることもできますが、返す価値はほとんどありません.FN番号を扱う場合はNaNを返す可能性があります。