2017-03-23 26 views
0

私はC++(大学プロジェクト)でBigNumクラスを作成するプロジェクトを持っています。 を取得するためにオペレータブラケットをオーバーロードすると言われましたが、問題はセットが無効だった場合です私たちは、私は、設定された作業角括弧[]オペレータオーバーロードC++

C++ : Overload bracket operators [] to get and set

を作ることが、私はoperatiを設定し、管理する方法を見つけることができませんでしたどのように見つけた検索で無効に

BigNum a; 
a[i]=11;//it is invalid because its >9 

のようなものである例外をスローする必要がありますC#での上で、あなたは簡単にそれを明確にするC++

でそれに相当するが、あなたはAラップwapperを、NumWapperを言う、定義することができますC#で、我々は

public int this[int key] 
{ 
    set 
    { 
     if(value<0||value>9)throw new Exception(); 
     SetValue(key,value); 
    } 
} 
+1

個々の数字のみを設定するか取得する必要がありますか?次に、可能なオーバーフローで生きなければならないか、 'operator []'関数によって返され、 'operator ='関数が値を検証する何らかのラッパークラスを作ります。 –

+1

リンク先の回答がわからないのはなぜですか?問題のあるコードを投稿してください。 – molbdnilo

+0

私はその答えには何の問題もありません@molbdnilo設定データが無効である場合、例外をスローしたい 無効なデータは1桁が負でも10よりも大きいことはできません –

答えて

1

を言うことができる何であるかの設定値を管理することができますBigNumの要素の参照。 BigNumのoperator=はラッパーを値で返します。

a[i]=11; 

は、NumWrapper x(...); x = 11のようなものです。今すぐoperator=のチェックをNumWrapperにすることができます。 NumWrapperで


class BigNum { 
public: 
    NumWrapper operator[](size_t index) { 
    return NumWrapper(array_[index]); 
    } 

    int operator[](size_t index) const { 
    return array_[index]; 
    } 
}; 

、など、いくつかの演算子をオーバーロード:ユーザーを防止するために、あなたはまた、NumWrapperのコピーを宣言し、プライベートとしてコンストラクタを移動し、彼の友人をBIGNUM行うことができます

class NumWrapper { 
public: 
    NumWrapper(int &x) : ref_(x) {} 
    NumWrapper(const NumWrapper &other) : ref_(other.ref_) {} 

    NumWrapper &operator=(const NumWrapper &other); 
    int operator=(int x); 
    operator int(); 

private: 
    int &ref_; 
}; 

あなたのラッパーをコピーすることからのコード。そのようなコードauto x = a[i]はコンパイルしませんが、ユーザコードはラップされた値をauto x = static_cast<T>(a[i])(冗長ですが)でもコピーできます。

auto &x = a[i]; // not compiling 
const auto &x = a[i]; // dangerous anyway, can't prevent. 

と思われます。


これらはまた、別のアプローチである:クラス定義されたユーザとしての要素を格納する、BigNumberElement言います。我々が使用することを容易にするためにBigNumberElement、このような比較として(も変換を介して行うことができます)、割り当て、コンストラクタなどに全体の集合演算子を宣言する必要が

class BigNum { 
// some code 
private: 
    BigNumberElement array_[10]; 
} 

:私たちは今のようにクラスBIGNUMを定義します。

auto x = a[i]は、ほとんどの場合、BigNumberElementのコピーを取得します。それに割り当てるだけで、例外がスローされ、実行時のオーバーヘッドが発生することがあります。でも、まだauto x = static_cast<T>(a[i])と書くことができます(それでもなお冗長ですが...)。そして、私が見る限り、予想外のコンパイル時のエラーメッセージは予期しない実行時の例外よりも優れています。

BigNumberElementをコピー/移動不可能にすることもできますが、最初のアプローチと同じになります。 (メンバー関数がBigNumberElement &を返した場合、予期しない実行時例外が戻ってきます。)

+1

NumWrapperとして要素を保存するだけでは、最初の場所?私は、要素をコピーしようとするテンプレート付きコードでは、あらゆる種類の問題を想像することができますが、代わりに参照先(NumWrapper)で元のものになります。 – josefx

+0

@josefx提案したアプローチについて簡単に分析しました。 NumWrapperのコピーはまだ悪い考えです。 – felix

0

以下は、operator[]から返された型foo::setterを定義し、operator=をオーバーロードして値を代入しますが、値が許容範囲内にない場合はスローします。

class foo 
{ 
    int data[10]; 
public: 
    void set(int index, int value) 
    { 
    if(value<0 || value>9) 
     throw std::runtime_error("foo::set(): value "+std::to_string(value)+" is not valid"); 
    if(index<0 || index>9) 
     throw std::runtime_error("foo::set(): index "+std::to_string(index)+" is not valid"); 
    data[index] = value; 
    } 
    struct setter { 
    foo &obj; 
    size_t index; 
    setter&operator=(int value) 
    { 
     obj.set(index,value); 
     return*this; 
    } 
    setter(foo&o, int i) 
    : obj(o), index(i) {} 
    }; 
    int operator[](int index) const // getter 
    { return data[index]; } 
    setter operator[](int index) // setter 
    { return {*this,index}; } 
};