わかりました、別の回答投稿で作成したポイントへの回答を追加する必要があります: (これを元の質問に編集した方がはるかに便利なので、下に表示されません。それに対する答え。
すべてのクリーンアップが常にデストラクタで行われる場合、catch ブロックにクリーンアップ コードを記述する必要はありませんが、C++ にはクリーンアップ アクションが行われる catch ブロックがあります。確かに、catch(...) のブロックがあり、そこではクリーンアップ アクションしか実行できません (確かに、ロギングを実行するための例外情報を取得することはできません)。
catch にはまったく別の目的があり、Java プログラマーはそのことに注意する必要があります。finally 句は、「無条件の」クリーンアップ アクション用です。ブロックがどのように終了しても、これを行う必要があります。Catch は条件付きクリーンアップ用です。このタイプの例外がスローされた場合、いくつかの追加アクションを実行する必要があります。
finally ブロックのクリーンアップは、例外がスローされたかどうかに関係なく実行されます。これは、クリーンアップ コードが存在する場合に常に実行したいことです。
本当に?このタイプで常に発生するようにしたい場合(たとえば、データベース接続が終了したら常に閉じたい場合)、一度定義してみませんか? タイプ自体で?データベース接続を使用するたびに try/finally を配置するのではなく、データベース接続を自動的に閉じますか?
それがデストラクタのポイントです。それらは、呼び出し元が考える必要なく、使用されるたびに、各タイプが独自のクリーンアップを処理できることを保証します。
C++ 開発者は、try ブロックから正常に終了したときに発生するコード フローの catch ブロックに表示されるクリーンアップ アクションを繰り返さなければならないことに最初から悩まされてきました。Java と C# のプログラマーは、finally ブロックで 1 回だけ実行します。
いいえ、C++ プログラマーはこれに悩まされたことはありません。Cプログラマーは持っています。そして、C++ にクラスがあることに気付き、自分自身を C++ プログラマーと呼んだ C プログラマーはクラスを持っています。
using
私は毎日 C++ と C# でプログラミングを行っていますが、データベース接続やクリーンアップが必要なものを使用するたびに、finally 句 (またはブロック) を指定する必要があるという C# のばかげた主張に悩まされていると感じています。
C++ では、「この型を使い終わったら、これらのアクションを実行する必要がある」ということを一度だけ指定できます。メモリの解放を忘れるリスクはありません。ファイル ハンドル、ソケット、またはデータベース接続を閉じるのを忘れるリスクはありません。私のメモリ、ハンドル、ソケット、およびデータベース接続がそれ自体を行うためです。
型を使用するたびに重複するクリーンアップ コードを記述しなければならないことが、どうして望ましいことでしょうか? 型自体にデストラクタがないために型をラップする必要がある場合は、次の 2 つの簡単なオプションがあります。
- このデストラクタを提供する適切な C++ ライブラリを探します (ヒント: Boost)
- boost::shared_ptr を使用してラップし、実行時にカスタム ファンクターを提供して、実行するクリーンアップを指定します。
Java EE アプリ サーバー Glassfish、JBoss などのアプリケーション サーバー ソフトウェアを作成する場合、例外情報をキャッチしてログに記録できるようにする必要があります。または、さらに悪いことに、ランタイムに陥り、アプリケーション サーバーが不意に突然終了します。そのため、考えられるすべての例外に対して包括的な基本クラスを用意することが非常に望ましいのです。そして、C++ にはまさにそのようなクラスがあります。std::例外。
CFront の時代から C++ を、この 10 年間のほとんどで Java/C# を使用してきました。根本的に似たものへのアプローチ方法に、巨大な文化的ギャップがあることは明らかです。
いいえ、あなたは C++ をやったことがありません。CFront、またはクラスを使用した C を実行しました。C++ ではありません。大きな違いがあります。答えを不自由だと言うのをやめれば、自分が知っていると思っていた言語について何かを学べるかもしれません。;)