2

次のようなコードがあります。

class ParseError: public exception {

protected:

  mutable string msg;
  int position;

public:

  explicit ParseError(const string& message, const int index) {
    msg = message;
    position = index;
  }

  virtual ~ParseError() throw () {
  }

  const char * what() const throw () {
    stringstream ss(msg);
    ss << "Parse error at position " << position << ": " << msg;
    msg = ss.str();
    return msg.c_str();
  }

};

それをスローすると、valgrind で単体テストを実行すると、次のように表示されます。

foo.h:102: メッセージの予期しない例外: 「位置 9 でエラーを解析: 予期しない文字が見つかりました: 何とか」

これは私が望んでいることですが、exception基本クラスが舞台裏で何をしているのかに興味がありました。拡張せずexceptionに残りのクラスをそのままにしておくと、次のようになります。

foo.h:102: メッセージ付きの予期しない例外: '不明な例外'

exception拡張せずにメッセージを表示するには、クラスに何を追加する必要がありますか?

ところで、私はruntime_errorおそらくexception. この場合、何がexception舞台裏で動いているのか興味がありますが、必ずしもベスト プラクティスに関するアドバイスを求めているわけではありません。

4

2 に答える 2

2

例外を処理しない場合に有用なエラー メッセージが表示されるという保証はありません。唯一の保証は、プログラムが を呼び出すことによって終了することstd::terminateです。

あなたの実装は、未処理の例外が から派生したものであることを識別し、std::exceptionその知識を使用して のオーバーライドを呼び出してwhat()エラー メッセージを生成できるようです。非標準の例外の種類については何も知らず、完全に無関係なクラスの関数と同じ名前を持っているという理由だけで関数をランダムに呼び出すべきではありません。

任意の型がスローされたときに何か役立つものを出力したい場合は、その型をキャッチして正しい処理を行うハンドラーが必要です。std::exceptionただし、何か他のものをスローする非常に正当な理由がない限り、から派生した型のみをスローすることをお勧めします。

于 2012-10-01T03:07:35.117 に答える
1

ここで 2 つの問題:

この関数では、それ自体に以下を入れmsgます:

  const char * what() const throw () {
    stringstream ss(msg);
                 ** ^^^
    ss << "Parse error at position " << position << ": " << msg;
    **                                                      ^^^

しかし、これはあまり重要ではありません。2 番目の問題は、メッセージの作成what()をコンストラクターに移動する必要があることです。what()それを返すだけです。

class ParseError: public exception {
protected:
  string msg;

public:
  explicit ParseError(const string& message, const int index) {
    ostringstream ss;
    ss << "Parse error at position " << position << ": " << message;
    msg << ss.str();
  }

  const char * what() const throw () {
    return msg.c_str();
  }

};
于 2012-10-01T03:53:18.043 に答える