私はLinuxでg ++を使用してC++で非常に単純なアプリケーションを作成しており、例外としていくつかの生の文字列をスローしようとしています(はい、私は知っています、それは良い習慣ではありません)。
私は次のコードを持っています(簡略化):
int main()
{
try
{
throw "not implemented";
}
catch(std::string &error)
{
cerr<<"Error: "<<error<<endl;
}
catch(char* error)
{
cerr<<"Error: "<<error<<endl;
}
catch(...)
{
cerr<<"Unknown error"<<endl;
}
}
そして、コンソールにUnknow error
が表示されます。しかし、リテラル文字列をstd::string
またはchar *
のいずれかに静的にキャストすると、期待どおりにError: not implemented
が出力されます。私の質問は、静的キャストを使用したくない場合にキャッチする必要があるタイプは何ですか?
char const*
ではなくchar*
でキャッチする必要があります。 std::string
やchar*
のようなものはそれをキャッチしません。
キャッチには、一致するタイプに関するルールが制限されています。仕様によると(「cv」は「const/volatileの組み合わせ」を意味するか、どちらも意味しません)。
ハンドラーは、次の場合にタイプEの例外オブジェクトに一致します。
- ハンドラーのタイプがcvTまたはcvT&であり、EとTが同じタイプ(最上位のcv修飾子を無視)であるか、または
- ハンドラーはタイプcvTまたはcvT&であり、TはEの明確なパブリック基本クラスです。
ハンドラーはタイプcv1T * cv2であり、Eはポインタータイプであり、次のいずれかまたは両方によってハンドラーのタイプに変換できます。
- プライベートクラス、保護されたクラス、またはあいまいなクラスへのポインタへの変換を含まない標準のポインタ変換(4.10)
- 資格の変換
文字列リテラルの型はchar const[N]
ですが、配列をスローすると配列が減衰し、実際には最初の要素へのポインタがスローされます。したがって、スローされた文字列リテラルをchar*
でキャッチすることはできません。これは、一致するときにchar*
をchar const*
に一致させる必要があるためです。これにより、const(修飾)が破棄されます。変換はadd const)にのみ許可されます。文字列リテラルのchar*
への特別な変換は、文字列リテラルを具体的に変換する必要がある場合にのみ考慮されます。
キャッチしているタイプにconst
を追加してみてください。const char*
(おそらくconst char* const
)。
文字列リテラルの正確なタイプは、const文字の配列です(たとえば、NULターミネータが含まれているため、const char [15]
)。配列は、スローされるとconst char*
に減衰します。これは、長さに関係ありません。
タイプは_const char[15]
_または_const char*
_である必要があります。
ただし、言語では型の値をスローすることは禁止されていませんが、例外としてネイティブデータ型を発生させるべきではありません。代わりに、std::exception()
インスタンスを発生させるか、独自の例外クラスを作成する必要があります。
問題は、constである何かをキャッチしようとしていることです。以下が機能します。
文字列リテラルのタイプはchar const *
です。既存のコードとの下位互換性のために、char *
への(非推奨の)変換が提供されています(ただし、それでもconst
として扱う必要があります-変更しようとするとUBになります)。
そのため、次のようなコードが機能するはずです。
#include <iostream>
using namespace std;
int main()
{
try
{
throw "not implemented";
}
catch(char const *error)
{
cerr<<"Error: "<<error<<endl;
}
return 0;
}
標準仕様のセクション2.14.5を確認してください。これは、3ページの文字列リテラルのタイプと種類を扱います。あなたが始めたことをしないでください、ただ言ってください:
throw std::exception("not implemented");
適切なと一緒に
catch (std::exception& pEx)
この「通常の」アプローチに何か問題がありますか...?