🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1185閲覧

エラー処理で文字列を投げる際、なぜstring で投げられないのか?

NASIJIRU

総合スコア15

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/02/22 02:03

try,throw→catchのエラー処理を書いている際、”aaa”という文字列をthrowしようと思いました。そこで、catchでその文字を受け取る型をstringにしたところ以下のエラーが出ました。

terminating with uncaught exception of type char const* Abort trap: 6

ロベールのc++を参照するとそこの型はconst char*だと書いてあり、以下のコードにすると動きました。なぜstring じゃだめなんでしょうか?

using namespace std; int main(){ try{ throw "aaa"; } catch(const char* a){     //ここの型をstringにすると動きませんでした。 cerr << a <<endl; return 0; } cout << 3 <<endl; return 0; }

以上よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ある型でthrowした例外は、同じ型、あるいは先祖クラスを宣言したcatchで受け取る必要があります。

const char *で投げた例外をstringでキャッチする、ようなことはできません。

投稿2021/02/22 02:06

maisumakun

総合スコア145971

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/02/22 02:07

もちろん、stringをthrowすればstringでcatchできます。
NASIJIRU

2021/02/22 02:09

ご回答ありがとうございます。 私は型に対して知識が不足しているようです。 "文字列"で投げた型はconst char*なのですか? constは変わらないこと、char は一文字を受け取る型、char*はcharのアドレスを受け取るポインタ変数と把握しております。
maisumakun

2021/02/22 02:14

> "文字列"で投げた型はconst char*なのですか? "文字列"の型は環境にもよりますが、const char[](書き換え不能なcharの配列)などの「文字型のconst配列」です。stringになることはありません。
maisumakun

2021/02/22 02:16

throw 式;とした場合を含め、(例外はありますが)配列を式中に書くと、自動的に「先頭要素を指すポインタ」として解釈されます。結果、throw "文字列";はconst char *を投げたものとして解釈されます。
NASIJIRU

2021/02/22 02:20

なるほど、先頭を示せば投げた文字列を参照できると行った構造だったのですね。理解しました。ご教授ありがとうございます。
yumetodo

2021/02/22 02:33

> maisumakun 規格ではいわゆるarray-to-pointer conversionとは別の文面で定義されているようです
guest

0

throw文の規格書を見てみましょう。

https://timsong-cpp.github.io/cppwp/n4861/expr.throw#2

Evaluating a throw-expression with an operand throws an exception; the type of the exception object is determined by removing any top-level cv-qualifiers from the static type of the operand and adjusting the type from “array of T” or function type T to “pointer to T”.

オペランドを伴うthrow文(訳注: catch文の中で単にthrow;のように書くと受けた例外を再度投げることができる)は例外を投げる。例外オブジェクトの型はオペランドの型から最上位のcv修飾子(訳注: const/volatile)を取り除いて、その後の型が要素型Tの配列型ないし関数型Tである場合、Tへのポインタ型に変換されたものになる。

どういうことか具体例で見てみましょう。

int a = 3; throw a;// => 例外オブジェクトはint型 const int b = 4; throw b;// => 最上位のcv修飾子を取り除くので例外オブジェクトはint型 int * const p1 = static_cast<int *>(malloc(sizeof(int))); if (p1) *p1 = 1; throw p1;// => 最上位のcv修飾子を取り除くので例外オブジェクトはint*型 int const * const p2 = p1; throw p2;// => 最上位のcv修飾子を取り除くので例外オブジェクトはint const*型 char a1[] = "aaa"; throw a1;// => 要素型charの配列型であるので変換され例外オブジェクトはchar*型 const char a2[] = "bbb"; throw a2;// => 要素型const charの配列型であるので変換され例外オブジェクトはconst char*型 throw "ccc";// => 文字列リテラルはconst修飾された文字列と終端文字を格納するに十分な大きさを持つ配列型となる。例えばconst char[4]型。これは要素型const charの配列型であるので変換され例外オブジェクトはconst char*型 int f() { return 3; } throw f;// => 関数型int ()なので変換され、例外オブジェクトはint (*)()型

ただまあ一般論としては、std::exceptionを継承するなんらかのクラスを投げるべきでしょう。

投稿2021/02/22 02:32

yumetodo

総合スコア5852

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問