web-dev-qa-db-ja.com

C ++でカスタム例外を作成する

私はC++を学んでおり、独自の例外を作成してLinuxでスローしようとしたときに経験しています。

実装をテストするための小さなテストプロジェクトを作成しました。以下は、例外クラスヘッダーファイルです。

class TestClass : public std::runtime_error
{
public:
    TestClass(char const* const message) throw();
    virtual char const* what() const throw();
};

例外クラスのソースファイルは

using namespace std;

TestClass::TestClass(char const* const message) throw()
    : std::runtime_error(message)
{

}

char const * TestClass::what() const throw()
{
    return exception::what();
}

私のメインアプリでは、次のように、例外をスローしてtry/catchでキャッチする関数を呼び出しています。

void runAFunctionAndthrow();

/*
 * 
 */
int main(int argc, char** argv) {
    try
    {
        cout << "About to call function" << endl;
        runAFunctionAndthrow();
    }
    catch (TestClass ex)
    {
        cout << "Exception Caught: " << ex.what() << endl;
    }

    return 0;
}

void runAFunctionAndthrow()
{
    cout << "going to run now. oh dear I need to throw an exception" << endl;

    stringstream logstream;
    logstream << "This is my exception error. :(";
    throw TestClass(logstream.str().c_str());
}

実行すると、次の出力が得られるはずです。

関数を呼び出す

今すぐ実行します。ああ、私は例外を投げる必要がある

キャッチされた例外:これは私の例外エラーです。 :(

代わりに私が得ているのは

関数を呼び出す

今すぐ実行します。ああ、私は例外を投げる必要がある

キャッチされた例外:std :: exception

「This is my exception error」という実際の例外メッセージではなく、std :: exceptionと表示されている最後の行に注目してください。

これはなぜですか、Windowsでは正常に動作しますが、Linuxではこれを行います。

さまざまな投稿で私が見たことから、私がしたことは正しいので、何が欠けているのか。

23
Boardy

what()は以下を返します。

_ return exception::what();
_

std::exception::what()からの戻り値は 次のように指定 です。

説明情報を持つヌル終了文字列へのポインタ。

それでおしまい。これ以上、他に何もありません。あなたが表示しているテキストは、確かに「説明的な情報」として適格です。そして、これはwhat()の戻り値の唯一の要件です(ここでは密接に関係のない他の1つを除く)。

言い換えれば、C++はwhat()で得られる内容の正確な内容を保証しません。 what()表示されるのは、what()です。

何らかの方法で例外を自分自身で記述したい場合は、what()の一部としてそれを実装するのはあなた次第です。

25
Sam Varshavchik

What()メソッドの独自の実装が必要か、コメントに記述されているstd::runtime_error::what()を使用します

いう:

_class TestClass : public std::runtime_error
{
    std::string what_message;
public:
    const char* what() override
    {
        return what_message.c_str();
    }
};
_

また、throw()の代わりにnoexceptを使用し、それらについて読んだ後でのみ使用してください- link

そして、あなたのトライキャッチで:

_catch (const TestClass& myException)
_

catch(TestClass myException)の代わりに-そうでない場合、潜在的に例外がスローされる可能性がある暗黙のコピーを行います。また、ポリモーフィズムを壊します:catch _pure virtual interface_実装インスタンスが必要な場合は、参照を使用する必要があります。

17
andrgolubev

Afaikが許可されていないstd :: exceptionにカスタムエラーメッセージを指定する方法が必要です。可能な解決策については、 this を参照してください。

0
Furkan Fidan