Visual Studio(Dinkumware?)はstd::exception
、メッセージ用の内部ストレージ†を含む実装を使用します。(文字列を受け入れる非標準のコンストラクターで完了します。)
このため、エラーメッセージを取得するために実際に仮想ディスパッチは必要ありません。スライスしても存続します。
派生オブジェクトが切り取られたため、よりオーソドックスな実装では、実際に一般的な例外メッセージが出力されます。(事実上、MSは同等のものを作成std::exception
しstd::runtime_error
ました。の戻り値std::exception::what
は実装定義であるため、これに問題はありませんが、結果を説明します。)
†ここの内部ストレージは大まかに使用されます。内部バッファはありませんが、const char*
とがありbool
ます。はconst char*
メッセージ(の戻り値what()
)を指し、bool
はバッファを削除する必要があるかどうかを決定するフラグです。
こんな感じです:
class msvc_exception // for exposition
{
public:
msvc_exception(const char* msg) :
mMsg(msg),
mDoDelete(false)
{}
msvc_exception(const std::string& msg) :
mMsg(copy_string(msg)),
mDoDelete(true)
{}
virtual ~msvc_exception()
{
if (mDoDelete)
delete [] mMsg;
}
virtual const char* what() const throw()
{
return mMsg ? mMsg : "unknown";
}
private:
const char* copy_string(const std::string& str)
{
const char* result = new char[str.size() + 1];
std::copy(str.begin(), str.end(), result);
result[str.size()] = 0; // null-terminate
return result;
}
};
bad_alloc
これで、次のように機能することがわかります。
class msvc_bad_alloc : // for exposition
public msvc_exception
{
public:
msvc_bad_alloc() :
msvc_exception("bad_alloc") // note: a static string, no dynamic storage
{}
};
メッセージは基本クラスに「存在する」ため、スライスはメッセージに影響を与えません。
GCCやLLVMのような他のコンパイラーは、それをもう少し簡単に実装します。
class orthodox_exception
{
public:
orthodox_exception(){}
virtual ~orthodox_exception() {}
virtual const char* what() const throw()
{
return "orthodox_exception";
}
};
class orthodox_bad_alloc :
public orthodox_exception
{
public:
const char* what() const throw()
{
return "orthodox_bad_alloc";
}
};
ここで、スライスはあなたの結果に影響を与えます。(とはいえ、結局のところ、常に参照によってキャッチします。)