あなたのコードは、あたかも別の言語に慣れているかのように見えます.C++では、this->x
(一例として)使用することは比較的まれです. コードが適切に作成されている場合は、アクセサーまたはミューテーターを使用しています。
私はこの特定の点でかなり変わっていますが、クライアントコードにアクセサーまたはミューテーターを直接使用させることは悪い考えであると言っているので、(もう一度)記録に残します。正直なところ、クライアント コードでオブジェクトの値を操作することが理にかなっている場合、クライアント コードは通常の代入を使用してその値を読み書きする必要があります。
どの値が割り当てられるかを制御する必要がある場合は、演算子のオーバーロードを使用すると、クライアント コードで醜い get/set 構文を強制することなく、その制御を行うことができます。具体的には、プロキシ クラス (またはクラス テンプレート) が必要です。ほんの一例として、get/set 関数が必要になる最も一般的な状況の 1 つは、特定の範囲に制限されるはずの数値のようなものです。はsetXXX
新しい値が範囲内にあるかどうかをチェックし、 はgetXXX
値を返します。
あなたがそれを望むなら、(かなり)単純なテンプレートは仕事をもっときれいに行うことができます:
template <class T, class less=std::less<T> >
class bounded {
const T lower_, upper_;
T val_;
bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}
void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}
public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}
bounded(bounded const &init)
: lower_(init.lower), upper_(init.upper)
{
assign(init);
}
bounded &operator=(T const &v) { assign(v); return *this; }
operator T() const { return val_; }
friend std::istream &operator>>(std::istream &is, bounded &b) {
T temp;
is >> temp;
if (b.check(temp))
is.setstate(std::ios::failbit);
else
b.val_ = temp;
return is;
}
};
これにより、コードが自己文書化にかなり近づきます。たとえば、次のようなオブジェクトを宣言するbounded<int>(1, 1024);
と、その意図が 1 から 1024 の範囲の整数であることがすぐにわかります。 1 および/または 1024 が範囲に含まれるかどうか。これは、クラスで int を定義することとはかなり異なります。また、クラスを見たすべての人が、setXXX を使用して (その時点では未知の) 値の境界のセットを適用する必要があることを理解することを期待しています。割り当てられます。
これらのいずれかをクラスに埋め込む場合、それをパブリック変数にすると、範囲は引き続き適用されます。クライアント コードには、構文に関する実際の引数はありません。他の場合と同様に、パブリック変数に代入するだけです。範囲外の値を代入しようとすると例外がスローされるという細かい点があります。理論的には、クラスはおそらくポリシー テンプレート パラメータを使用して、その場合に何を行うかを正確に指定する必要がありますが、それを気にする本当の理由はありませんでした。