tryを使ったエラー処理について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

tryを使ったエラー処理について

#1

投稿記事 by taketoshi » 14年前

こんばんわ、お世話になります
表題の通り、try~catch構文を使ってエラー処理を実装していきたいと思っています。
今まで、エラー処理は、戻り値をチェックして、もしエラーであれば
変数を初期化したり、メッセージを出したりするような処理を施していました。

C++の勉強を進めていく中で、try文がエラー処理に使えるということなので、使ってみたいと思い質問させて貰います。
以下の様にテストでコードを書いてみました

コード:

			//サーバースタート
			case MAKEINTRESOURCE(ID_START):
				try{
					bRet = odbc.ConnectSQL();
					if(bRet == FALSE){
						Error err;
						throw err;
					}
				}catch(Error e){
					//エラークラス内のSQL関係を初期化するメソッドを呼び出す
					e.InitSQL();
					return 0;
				}

				try{
					bRet = ws.CreateListen(hWnd);
					if(bRet == FALSE){
						Error err;
						throw err;
					}
				}catch(Error e){
					//エラークラス内のWinsock関係を初期化するメソッドを呼び出す
					e.InitWinsock();
					return 0;
				}
これはサーバープログラムなのですが、戻り値をチェックしてFALSEならばエラークラスをthrowして
エラークラスからそれぞれの変数を初期化するメソッドを呼び出しています。
そして、一旦returnしてそれ以降の処理を中断しています。

そこで質問なのですが、なんというかこれでは冗長というか、昔の戻り値を逐次チェックするのと変わらない感じがしまして
もっと上手い実装の仕方があるのではないかと思い質問させてもらいます。

一般的にtry文を用いてエラークラスをthrowしエラー処理をする場合、どのように実装するのでしょうか。
サンプルなど有りましたらご提示頂けると幸いです。
よろしくお願いします。

たかぎ
記事: 328
登録日時: 15年前
住所: 大阪
連絡を取る:

Re: tryを使ったエラー処理について

#2

投稿記事 by たかぎ » 14年前

まず指摘しておかないといけないのは、catchで例外オブジェクトを補足する場合、値で受けるのではなく、参照で受けるようにすべきだということです。
Errorの型が、単なる整数型とかであればよいのですが、クラス型の場合、参照で受けるようにしないと、いろいろと問題が起きる原因になります。

次に、例外を送出する方法ですが、普通は呼び出した関数の中でエラー判定を行い、必要に応じて例外を送出するようにします。
ただし、何でもかんでも例外を使うのは正しい方法ではありません。
普通に起こる事象を通知するには、例外より返却値等を用いるほうが得策です。
致命的かそれに近い事象や、普通は起こりえない事象を通知するためにだけ例外を使うようにしましょう。

taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

Re: tryを使ったエラー処理について

#3

投稿記事 by taketoshi » 14年前

御回答ありがとうございます。

ひとつ質問があります。クラスを参照で渡さなければ起こりうる問題って具体的になんでしょうか。
これだとオブジェクトのコピー(?)を渡しているだけなので、そういった絡みで起こりうる問題でしょうか。

関数内からのエラー処理は教本の猫C++に簡単なサンプルが載っていたので、これを参考に実装します。


>ただし、何でもかんでも例外を使うのは正しい方法ではありません。
>普通に起こる事象を通知するには、例外より返却値等を用いるほうが得策です。

これも疑問のうちの一つでした。通常処理では、返却値をチェックした処理を実装していきたいと思います。

たかぎ
記事: 328
登録日時: 15年前
住所: 大阪
連絡を取る:

Re: tryを使ったエラー処理について

#4

投稿記事 by たかぎ » 14年前

taketoshi さんが書きました:ひとつ質問があります。クラスを参照で渡さなければ起こりうる問題って具体的になんでしょうか。
これだとオブジェクトのコピー(?)を渡しているだけなので、そういった絡みで起こりうる問題でしょうか。
一番わかりやすいのはスライシングです。
たとえば、次のようなケースを考えてみてください。

コード:

try
{
  throw std::runtime_error("例外発生");
}
catch (std::exception e)
{
  // eを使った何らかの処理
}

taketoshi
記事: 222
登録日時: 15年前
住所: 日本国

Re: tryを使ったエラー処理について

#5

投稿記事 by taketoshi » 14年前

たかぎさん、ありがとう御座います。

std名前空間を使ったプログラムをあまり書いたことがないので、まずそれについてググってきました。
runtime_errorクラスははexceptionクラスの派生型の様ですね。
ということは、子クラスから例外通知を投げて、親クラスで処理していると考えました。
次のコードを試しに書いてみました

コード:

// try.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include<iostream>
#include<windows.h>

using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	try{
		int x;
		x = 10;
		if(x = 10){
			throw std::runtime_error("test");
		}
	}
	catch(std::exception e){
		cout << e.what() <<endl;
	}
	return 0;
}
親クラスで例外処理をしようとすると「何もデータないよ!」と怒られました。
どうやら子クラスの情報が欠如している感じです。
catchのほうで別のオブジェクトを宣言しているから受け取れて居ないのかな?


exceptionを参照で受け取った場合はきちんとtestの文字が出力されました。結果として値渡しですと情報が欠如する問題が起こりうるようですね。
まだ完璧に使いこなせる自信はないですが、この手法を取り入れてみたいと思います。ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る