0

最近、自分のプログラミング スタイルとそれを改善する方法をよく調べています。まず、私の現在の役割では、私は唯一のプログラマーです。その結果、好きなだけハックなものを作ることができますが、より優れた、より健全なプログラマーになるために本当に努力しています。

また、私のバックグラウンドは主に C ベースで、必要に応じて基本的に C++ を C のスーパーセットとして使用していました。その結果、次の難問に出くわしました。

私はいつも #define ERROR_FUNCTION_BLEW_UP -2 のようなものでエラー コードを定義してきました。正直なところ、-2 を格納するためにメモリを割り当てる必要がないため、そうすることの利点がわかります。ただし、C++ では、競合する 2 つのマクロ間の衝突の可能性が少ないため、const 変数を使用する利点がわかりました。

その結果、C++ でエラー コードを実装する最もクリーンな方法は何だろうと考えていました。つまり、「if (return_value == ERROR_FUNCTION_BLEW_UP)」に類似したことを行うことで、クライアントが特定の関数の戻り値を確認できるようにしたいと考えています。各クラスに const 変数を追加しようとしましたが、コードが正しく表示されません。つまり、クライアントは「if (return_value == MyClass.kErrorFunctionBlewUp_)」の行に沿って何かをチェックするようになりました。定数をクラスのパブリックメンバーにするのではなく、これを達成するためのよりクリーンな方法はありますか?

また、私の質問に追加すると、myClass は基本クラスであり、MyDerivedClass にエラー コードを追加したいと考えています。これに対処し、マクロを回避する最善の方法は何ですか?

ご協力ありがとうございました。

4

2 に答える 2

6

用途enum:

enum Errors
{
    NO_ERROR = 0,
    FUNCTION_BLEW_UP,
    WTF_THIS_SHOULDNT_HAPPEN,
};

std::exceptionまた、より適切な場合は、例外の使用を検討してください (参考)。

于 2013-06-08T01:52:17.397 に答える
0

本当にマクロを置き換えたい場合は、それらを定数に置き換えます。定数には内部リンケージ (つまり、変換単位 (「ファイル」) に制限されている) があるため、コンパイラは、マクロよりも多かれ少なかれ 1 バイトを使用することなく、その使用をインラインの定数に簡単に置き換えることができます。マクロは通常のコード規則に従わないため、ALL_UPPERCASE をマクロに保持するのが通例であることに注意してください。したがって、それも変更する必要があります。

次に、C++ では、通常、呼び出し元がチェックする必要があるリターンコードを使用するのではなく、自動的に伝播する例外を使用します。エラーコードを保持したい場合は、列挙型または定数を使用して名前空間に入れることができます。列挙は、周囲の名前空間またはクラスに漏れることに注意してください。これにより、それらを 1 つのレベルでラップすることが推奨されます。

namespace errorcode
{
    enum type
    {
        printer_on_fire,
        volume_not_formatted,
        bluescreen
    };
}

例外には、何が失敗したかをさらに特定するエラー コードが含まれることがあります。それらを指定する 1 つの方法を次に示します。

struct error:
    std::runtime_error
{
    ...

    enum code
    {
        printer_on_fire,
        volume_not_formatted,
        bluescreen
    };

    code fault;
};

コードをネストする必要がないことに注意してください。既存のerrorcode::type上記で例外タイプを構築することもできます。ただし、列挙は周囲の名前空間を汚染するため、いくつかのネストは便利です。

そうは言っても、「クラスの前にファイルの先頭に配置しますか」と尋ねますが、ここでは誤解があります。まず、すべてのファイルにクラスが含まれているわけではありません。次に、クラスを含むすべてのファイルにそれらが 1 つだけ含まれているわけではありません。たとえば、エラーコードのコレクションがクラス階層全体で使用される場合、別のファイルで定義して、それらの 1 つだけに属していないこと、および関連する非クラスで使用できることを明確にすることは理にかなっています。関数も。そのファイルには、たとえば、デバッグ用の文字列に変換する関数と、それらの 1 つを運ぶ例外タイプも貼り付けます。

于 2013-06-08T08:11:39.710 に答える