1

ライブラリを作成しています。固定長の文字列クラスを作りたい。

#include <string>
#include <iostream>

#define OK 0
#define TOO_LONG 1
#define UNALLOWED_CHARACTERS 2

struct MyString {
    MyString(int l)
        : m_length(l) { }
    struct exception {
        exception(int t, MyString *p)
            : type(t), ptr(p) { }
        int type;
        MyString *ptr;
    };
    int set(const std::string& name);
    void set2(const std::string& name) throw(exception);

    std::string m_str;
    int m_length;
};

int MyString::set(const std::string& s)
{
    if(s.size() > 64) {
        return TOO_LONG;
    } else if(s.find('~') != std::string::npos) {
        return UNALLOWED_CHARACTERS;
    } else {
        m_str = s;
        return OK;
    }
}

void MyString::set2(const std::string& s) throw(exception)
{
    if(s.size() > m_length) {
        throw exception(TOO_LONG, this);
    } else if(s.find('~') != std::string::npos) {
        throw exception(UNALLOWED_CHARACTERS, this);
    } else {
        m_str = s;
    }
}

int main()
{
    using namespace std;
    //OPTION 1
    {
        MyString s1(10);
        MyString s2(10);
        int code;

        code = s1.set("abcdefghijX");
        switch(code) {
        case TOO_LONG:
            //handle <--
            break;
        case UNALLOWED_CHARACTERS:
            //handle
            break;
        default:
            //ok!
            break;
        }

        code = s2.set("abcdefghi~");
        switch(code) {
        case TOO_LONG:
            //handle
            break;
        case UNALLOWED_CHARACTERS:
            //handle <--
            break;
        default:
            //ok!
            break;
        }
    }

    //OPTION 2
    {
        MyString s1(10);
        MyString s2(10);
        try {
            s1.set2("abcdefghijX");
            s2.set2("abcdefghi~");

        } catch(MyString::exception &e) {
            cerr << "MyString::exception: ";
            auto p = e.ptr;
            if(p == &s1) cerr << "s1 ";
            else if(p == &s2) cerr << "s2 ";
            switch(e.type) {
                case TOO_LONG: cerr << "too long"; break;
                case UNALLOWED_CHARACTERS: cerr << "unallowed characters"; break;
            }
            cerr << endl;
        }

    }
}

MyString :: set()のどのバージョンを使用すべきかわかりません。そのような場合の慣習は何ですか?この例では、デモンストレーションの目的でSTLを使用しました。

4

2 に答える 2

1

特別な理由がない限り、標準ライブラリ関数の動作を模倣することをお勧めします。ところで、tr1 以降、STL には固定長の文字列クラスが組み込まれています。それが何をするのか見てみましょう。私が手元に持っている唯一の実装例は、Visual C++ 2010 です。


std::tr1::array<int,5> arry;
arry[10] = 42; // Oopsie. There is no element 10.

「デバッグ」バージョンとしてコンパイルして実行すると、アサートエラーが発生します。「リリース」用にコンパイルすると、攻撃的なステートメントは静かに...何もしません。それは存在するすぐに最適化されています。わかりました、多分それは常に人が望むものではありません. STL、または少なくとも Microsoft の実装を模倣することについて私が言ったことは忘れてください。意識の列車は続く...

プログラムが範囲外のセルを設定しようとすると、それはプログラムの論理エラーであると言っても過言ではありません。ミッション クリティカルなソフトウェアでは、そのような状況に対処して回復するためのコードを配置し、それが決して起こらないようにすることをお勧めします。

答えは、std::out_of_range 型の例外をスローすることです

そこで。

于 2012-08-09T03:38:24.573 に答える
1

一般に C++ では、例外を使用して、現在のコンテキストで回復できないエラーを示すことをお勧めします。しかし、それは目的によります。(効率のために) 例外を使用せずに組み込み環境でライブラリをコンパイルしたい場合は、リターン コードを使用する必要があります。

戻りコードを使用する API を例外を使用する API にラップするのは簡単ですが、その逆はありません。

編集:

例外処理を使用しないことが理にかなっている理由をさらに説明します。

通常、例外処理では、コール スタックに配置する必要があるブロックに関する追加情報が導入されtry/catchますが、これらの情報を構築および確認するためにパフォーマンスが低下します。

参照: C++0x 例外のパフォーマンス

于 2012-08-05T15:34:01.877 に答える