4

そこで、Java Exceptionクラスに基づいて、C++用の単純な基本Exceptionクラスを作成しようとしています。すでに素晴らしいライブラリがあると確信していますが、私はこれを実稼働コードではなく練習用に行っています。興味があり、常に学びたいと思っています。Javaの例外が行うことの1つは、私も実装したいのですが、「原因」の概念です。Javaでは、原因のある新しい例外は次のようになります。

Exception cause = new Exception();
Exception newExcept = new Exception(cause);

ただし、C ++では、コンストラクターへの引数として例外を渡すことが、コピーコンストラクターの呼び出し方法です。したがって、例外をコピーすることと、原因を指定して新しい例外を作成することの間には、概念的な断絶があります。明らかに、これはJavaでは問題ではありません。

私はこれを処理するための最良の方法は何であるかと思っているだけだと思います。私が持っていたいくつかのアイデアは次のとおりです。

  • ダミー変数で区別する
  • 新しい例外を作成し、setCause()メソッドを呼び出すだけです
  • コピーコンストラクターのようなものException(Exception &)であり、原因のあるコンストラクターはException(Exception *)

ありがとう

4

4 に答える 4

5

例外(スタックに割り当てられた場合(これを強くお勧めします))は、catch句の後で解放されます。したがって、新しく作成された例外に「内部」例外のコピーを作成する必要があります。例外の基本クラスをキャッチすると、例外にcloneメソッドを指定しない限り、正しいタイプが失われます。

#include <string>
#include <exception>

class MyBaseException : public std::exception
{
public:
    MyBaseException(const std::string& what = std::string("MyBaseException"))
        : m_BaseException(0), m_What(what) {}  //Constructor without inner exception

    MyBaseException(const MyBaseException& innerException, const std::string& what = std::string("MyBaseException"))
        : m_BaseException(innerException.clone()), m_What(what) {}  //Constructor with inner exception

    template <class T>  // valid for all subclasses of std::exception
    MyBaseException(const T& innerException, const std::string& what = std::string("MyBaseException"))
        : m_BaseException(new T(innerException)), m_What(what) {}

    virtual ~MyBaseException() throw()
        { if(m_BaseException) { delete m_BaseException; } } //don't forget to free the copy of the inner exception
    const std::exception* base_exception() { return m_BaseException; }
    virtual const char* what() const throw()
        { return m_What.c_str(); } //add formated output for your inner exception here
private:
    const std::exception* m_BaseException;
    const std::string m_What;
    virtual const std::exception* clone() const
        { return new MyBaseException(); } // do what ever is necesary to copy yourselve
};

int main(int argc, char *argv[])
{
    try {
        try {
            throw std::exception();
        }
        catch(const std::exception& e) {
            throw MyBaseException(e, "bad");
        }
    }
    catch (const MyBaseException& e) {
        throw MyBaseException(e, "even worse");
    }
    //throw MyBaseException(1, "will not compile");
}
于 2010-09-10T06:34:01.653 に答える
2

ファクトリーモデルを使用できます。

Exception cause = Exception.Create();
Exception newExcept = Exception.Create( Exception cause );
于 2010-09-10T04:47:12.493 に答える
1

原因例外の文字列を現在の例外に追加するだけです。

try
{
    throw std::runtime_error("Failed to work");
}
catch(std::exception const& e)
{
    // New exception (add origianl exception text).
    throw std::runtime_error(std::string("We were doing poobar when: ") + e.what());
}
于 2010-09-10T04:56:15.513 に答える
0

あなたの質問は不明確であり、Javaでさえ適切に見えませんが、ライブラリによってサポートされているJavaイディオムです。あなたが説明するイディオムは、元の例外を、再スロー時に作成する例外への引数として渡すことだと思います。

解決策は、library_exception(またはあなたがそれを呼びたいもの)を作成することです

class library_exception: public std::exception
{
 ...
 public:
   library_exception(const  std::exception &e)
 ...
}
...
catch(const std::exception &e)
{
  ...
  throw library_exception(e);
}

コピーコンストラクタが呼び出されない異なるクラス。

于 2010-09-10T05:47:42.317 に答える