C++で、例外処理としてtryがあるのですが、どういった使い方をするのでしょうか?
それと、catchも使い方がわかりません。
どなたか教えてください。
よろしくお願いします。

A 回答 (1件)

「例外」自体が分からない、ということでしょうか、それとも「例外」はなんとなく


理解しているが、try と catch が分からないんでしょうか。

例外とは、その名の通り、こんなはずではなかった、ということを表すものです。
つまり、予期せず起こるものです。

でも、例外が起きたときの対処は、それぞれに対して1対1で対処法があると
いうよりは、細かいことは気にせずまとめて処理できることの方が多いです。

「こんなはずではなかった!」というときには、例外を *投げます* (throw)。
投げられた例外は、例外の後始末をする誰かが *受け取ります* (catch) 。
例外を受け取るために、範囲が指定できます。例外が起きるかどうか試してみる
という意味で try というブロックがあります。

例外は概念で、例外の実体にはクラスを指定できます。


下に示すプログラムは、ふたつ数字を入力して割り算をした結果を表示する
ものです。0では割れませんから、そのときは例外としています。雰囲気が
分かるでしょうか?

#include <iostream.h>

class ExceptionDivideByZero {
private:
  int x_, y_;
public:
  ExceptionDivideByZero(int x, int y) : x_(x), y_(y) {}
  void printMessage();
};

void ExceptionDivideByZero::printMessage()
{
  cout << "Divide By Zero. " << x_ << " / " << y_ << endl;
}


int divide_number(int a, int b)
{
  if (b == 0) {
    throw ExceptionDivideByZero(a, b);
  }
  return a / b;
}

int main()
{
  int a, b, c;
  try {
    cerr << "a: "; cin >> a;
    cerr << "b: "; cin >> b;
    c = divide_number(a, b);
    cout << "a / b = " << c << endl;
  } catch (ExceptionDivideByZero ex) {
    ex.printMessage();
  }
  return 0;
}

★実行結果

$ prog
a: 4
b: 2
a / b = 2
$ prog
a: 5
b: 0
Divide By Zero. 5 / 0

# 「伝わるかな~」という意味で自信無しにしておきます
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Qtry~catchの使用方法

プログラミング超初心者です。
現在、C++やjavaの勉強をしているのですが、
・try~catchとはなんぞや
・どんな処理をするときにtry~catchをつけなければいけないのか
がよくわかっていないので、教えていただけないでしょうか?
また、そういったことが載っているサイトも併せて教えていただければうれしいです。

Aベストアンサー

これは、「例外処理」のためのものです。
動きとしては、
try { ... } の中で発生した「例外」に対する処理を、 catch { ... } の中に記述しますということになります。
これは、例外(おおざっぱに言えば、内部的なエラー)の「発見」と「発生」と、「リカバリ」に関わる分離の思想から考えられたものです。

例外処理がない場合、エラーの処理は、
・エラーが発生してないかどうか確認する
・エラーが発生していたら、その場で処理する
ということになります。

この方法には、問題がああって、本来の処理とエラー処理が混在して処理の見通しが悪くなるということになります。
例えば、以前の(失敗したら NULL を返す仕様の new 演算子の場合)

classA a = new classA(1, 0);
if (a == 0)
goto エラー処理;
classA b = new classA(1, 1);
if (b == 0)
goto エラー処理;
など。
これに対して、最近の(失敗したら、bad_alloc 例外をスルーする ) new だと、

try
{
classA a = new classA(1, 0);
classA b = new classA(1, 1);
}
catch(bad_alloc) // これは、new で失敗した時に投げられる例外
{
エラー処理
}

となります。
こうすれば、if (a == 0) が本来の処理ではなく、エラーチェックだったのがわかります。

また、往々にして、エラーの検出箇所(それがエラーだったとわかる場所)と、エラーの発生場所(エラーを発生させてしまった場所)は違うものです。

例えば、平方根を算出する関数はマイナスの引数を受け付けません。このため、普通は関数の中で引数がマイナスでないかどうかチェックをします。
おかしな引数を渡していれば、関数の中で引数がおかしいかどうかわかります。
しかし、この間数の中では、なぜ引数がおかしいのかはわかりません。
入力ミスなのか、計算ミスなのか。

一方で、引数がおかしくなった原因は、この間数を呼び出す箇所(の近く)にあることが多いわけです。
ですから、おかしな引数のリカバリは、こちら(発生場所)で行う方が妥当です。

もちろん、関数を呼び出す前にあらかじめ引数の妥当性をチェックするというのも正しい考え方です。
ただ、場合によっては、通常処理の流れでプログラムを作り、その処理の中で(この部分を try で囲む)エラーが検出された箇所(実際には、例外処理がスルーされる場所)の情報をもとに、エラーのリカバリ(ここが、catch セクション)を行うという形にするとすっきりする場合があります。

これは、「例外処理」のためのものです。
動きとしては、
try { ... } の中で発生した「例外」に対する処理を、 catch { ... } の中に記述しますということになります。
これは、例外(おおざっぱに言えば、内部的なエラー)の「発見」と「発生」と、「リカバリ」に関わる分離の思想から考えられたものです。

例外処理がない場合、エラーの処理は、
・エラーが発生してないかどうか確認する
・エラーが発生していたら、その場で処理する
ということになります。

この方法には、問題がああって、本来の...続きを読む

QC,C++,C++/CLIの構造体とクラス

C++の構造体・クラスって、メンバのアクセス指定子のデフォルトが
privateかpublicかという違い「だけ」しか全くないのでしょうか?

クラスにおける
value class / ref class
という分類はC++/CLIのもので
これについては
value class の方は C言語の構造体に近いという事でいいでしょうか?

ref classの方は
ネイティブのC++のクラスを
マネージ用にしたようなもので

C++/CLIの構造体は
C++のそれと同じで
OKですか?

そしてそれらの構造体には、値型・参照型といった分類はないのでしょうか?

Aベストアンサー

> ということは、structも継承可、という事でしょうか?

structでも継承可能です。

> 継承のアクセス指定の方は
> クラスと構造体ではどうなるのでしょうか?

class A : Base {};



class A : private Base {};

と等価です。
一方、

struct A : Base {};



struct A : public Base {};

と等価です。

> そして「集成体」というのが初めて知ったのですが
> これはいわゆる、配列や・・・ある条件下でのクラス・・?
> なのでしょうか?

配列と以下の条件をすべて満たすクラスのことです。
・ユーザー定義のコンストラクタを持たない
・非公開または限定公開のメンバを持たない
・基底クラスを持たない
・仮想関数を持たない

ちなみにC言語の集成体は、配列と構造体の総称です(共用体は集成体ではありません)。

QC++の例外処理について

C++にjavaのような例外処理ができるのを知りました
構文は

try
{
stat1
}
catch(except-decl)
{
stat2
}
finally
{
stat3
}
stat4

ただし
stat1:例外が発生する可能性があるステートメント
stat2:例外が発生したときに実行するステートメント
stat3:例外が発生しなくても実行するステートメント
stat4:ステートメント
except-decl:捕獲する例外の宣言
です

ここで質問です
(1)
冷害が発生したときstat4は実行されるのでしょうか?
されない場合にはその後どう言う処理がなされるのでしょうか?
(2)
except-declはどうのような記述がなされるのでしょうか?
(4)
例外を発生させる構文
throw except
(except:発生させる冷害)
のexceptの部分にはどのような記述がなされるのでしょうか?


よろしくお願いします

Aベストアンサー

> 例外処理は主にデバッグのときだけに使われるのでしょうか?
> 怪しい処理は最終的にはつかわないようにすると思ったので気になります

いえいえ、その言葉どおり「例外的な処理を記述するため」のものです。

たとえば、普通はつながっているはずのマシンと通信するような処理で、たまたま相手が
メンテ中で止まっており通信ができない、って場合は、例外で処理するのがスマートです。

# 「怪しい処理」って、なんか、発想が面白い :-)

蛇足になりますが、No.5 の回答について。

layer13> それからもう一つ、JAVAが出てくる前からC++に例外処理は有ります。
layer13> C++が出来たのは1980年代ですからね。その辺りを勘違なさいませぬように。
layer13> #ANSI制定も1995年くらい?

c++ は 1980年代の前半からですが、最初は C のソースへのトランスレータとして
実装されました (cfront という)。
最初の頃は、例外も実装されていません。

ANSI C++ は、1997年の11月に採択され、正式に ISO に承認されたのは次の年の春か夏だったと思う。

> 例外処理は主にデバッグのときだけに使われるのでしょうか?
> 怪しい処理は最終的にはつかわないようにすると思ったので気になります

いえいえ、その言葉どおり「例外的な処理を記述するため」のものです。

たとえば、普通はつながっているはずのマシンと通信するような処理で、たまたま相手が
メンテ中で止まっており通信ができない、って場合は、例外で処理するのがスマートです。

# 「怪しい処理」って、なんか、発想が面白い :-)

蛇足になりますが、No.5 の回答について。

layer13> そ...続きを読む

Qtry{}catch(){}とデストラクタの関係を教えてください。

try-catchでメモリ確保を含むクラスをスローした場合、デストラクタはどの時点で働くのか、教えてください。たとえば、↓の使いかたは大丈夫でしょうか?

【1】
try{
 throw(CError(100, "エラー情報"));
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
}

【2】
try{
 CError err(100, "エラー情報");
 throw(err); // (1)
}catch(CError& err){
 //ここでerrを参照しても問題ないのでしょうか?
 //まだデストラクタはちゃんと動作するのでしょうか?
 //catchが呼び出し元のメンバであったりしても大丈夫なのでしょうか?
}

宜しくお願いします。

Aベストアンサー

【1】【2】どちらの場合も問題がありません。
コンパイラが必要に応じてerrオブジェクトのコピーを作成します。
デストラクタが呼び出されるタイミングはコンパイラに依存するところもあると思いますが、
例えばVC7.1では【2】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) CErrorクラスのテンポラリオブジェクト(以下a)のコピーコンストラクタが呼び出される。
(3) errオブジェクトのデストラクタが呼び出される
(4) catch文まで到達
(5) aオブジェクトのデストラクタが呼び出される。

VC7.1では、【1】は以下のように動作します。
(1) errオブジェクトのコンストラクタが呼び出される
(2) catch文まで到達
(3) errオブジェクトのデストラクタが呼び出される。

コンパイラがオブジェクトのコピーを省略しているようです。

QC/C++言語で日本語処理

C言語orC++言語で日本語の処理がしたいのですが方法がわかりません。
以下のlen,mid関数を作成したいのですが、どうすればよいのでしょうか。
文字コードはSJIS(CP932?)とします。

また、C言語のソースは基本的にSJIS書き、コンパイルすると解釈してよいですか?WindowsはSJIS? LinuxはEUC-JP??

#include <stdio.h>
#include <string.h>

void main(void){
char moji[] = "パソコンでABC";

// この結果は「パソコンでABC」, 19, 18で正しいです。
printf("%s\n%d\n%d", moji, sizeof(moji), strlen(moji));

// 文字数換算で8と出力させる方法
// 汎用関数 Len関数を作る Lenbでない。この場合 len(moji)の結果は「8」

// 文字数換算で6文字目から3文字数カットしたABCを出力する。
// 汎用的に MID関数を作る MIDBでない。この場合 mid(moji, 3, 5)の結果は 「コンでABC」

}

あと、詳しい書籍等もご存知の方教えてください。

C言語orC++言語で日本語の処理がしたいのですが方法がわかりません。
以下のlen,mid関数を作成したいのですが、どうすればよいのでしょうか。
文字コードはSJIS(CP932?)とします。

また、C言語のソースは基本的にSJIS書き、コンパイルすると解釈してよいですか?WindowsはSJIS? LinuxはEUC-JP??

#include <stdio.h>
#include <string.h>

void main(void){
char moji[] = "パソコンでABC";

// この結果は「パソコンでABC」, 19, 18で正しいです。
printf("%s\n%d\n%d", moji, sizeof(moji),...続きを読む

Aベストアンサー

参考までにGNU C++の場合を書いてみます。

ソースファイルでCP932を使う場合、コンパイルオプションで-finput-charset=cp932を指定する必要があります。実行文字コードは、ロケールにあわせて-fexec-charsetで指定してください。(デフォルトではUTF-8になります)

内部的な処理は、多バイト文字列のままでは面倒なので、いったんワイド文字列に変更します。mbstowcs等で変換するか、libiconvでも使いましょう。(もちろん、ICUなどの外部ライブラリでもOKですし、std::codecvtファセットを使ってもOK)
ワイド文字列になってしまえば、あとはstd::wstringを使えば簡単です。

VBのLenは、std::wstring::sizeまたはstd::wstring::lengthを使います。
VBのMidは、std::wstring::substrを使うか、std:wstringのコンストラクタで対応できます。

以下、未検証ですが、コードをのせておきます。

#include <iostream>
#include <string>
#include <locale>
#include <clocale>
#include <cstdlib>

int main()
{
 std::setlocale(LC_CTYPE, "");
 std::wcout.imbue(std::locale(""));

 wchar_t wcs[16];
 mbstowcs(wcs, "パソコンでABC", sizeof(wcs)/sizeof(wcs[0]));
 std::wstring moji(wcs);

 std::wcout << L"Len(moji): " << moji.length() << std::endl;
 std::wcout << L"Mid(moji, 3, 5): << moji.substr(3, 5) << std::endl;
}

参考までにGNU C++の場合を書いてみます。

ソースファイルでCP932を使う場合、コンパイルオプションで-finput-charset=cp932を指定する必要があります。実行文字コードは、ロケールにあわせて-fexec-charsetで指定してください。(デフォルトではUTF-8になります)

内部的な処理は、多バイト文字列のままでは面倒なので、いったんワイド文字列に変更します。mbstowcs等で変換するか、libiconvでも使いましょう。(もちろん、ICUなどの外部ライブラリでもOKですし、std::codecvtファセットを使ってもOK)
ワ...続きを読む


人気Q&Aランキング

おすすめ情報