- 締切済み
個々のデータの正当性チェックの関数について教えて下さい
クラスの中に10個メンバ変数があるとします。それぞれのメンバ変数にデータを代入する時に、そのデータの正当性をチェックする関数をクラス内に作るとします。10個のメンバ変数は各々正当である値の型や範囲が異なるんで、正当性チェック関数は10個用意しなければいけませんか? それとも、テンプレートなぞを使えば1個の関数にできるのでしょうか? 最もよく使うような方法を教えて下さい。 正当性チェックの内容は、型チェックとデータ範囲くらいです。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- mikaemi
- ベストアンサー率50% (33/65)
補足: たとえば、今、ご自分で作成されているプログラムのコードを貼り付けて、こういうことをしたいと具体的に書いておけば、jacta さんも、「普通は、…よいだけです。」という、つれない回答ではなく、具体的なサンプルのようなものを提示してくれてたのかもしれませんから^^
- mikaemi
- ベストアンサー率50% (33/65)
「さぁ~て、いい回答は出てるかな。。。」という感じで、何日か後にまとめて見るのでしょうが、aneja さんはあまり反応がないので、まとめるとはどういうイメージでいってるのかとか、単にタイピング量を減らしたいだけなのかとか、どうして型チェック(動的型チェック?)したいのかとか、わたしは十分に理解できていません^^ テクニックなどは、もっともよく使う方法・標準的方法だから使うというのではなくて、効率・理解しやすさ・移植性など考慮して、各々のプログラムにあったものを採用するのがいいんじゃないですかね?^^ もちろん、「よく使う方法」が採用されることが多いのでしょうけど(笑) データ範囲のチェックをまとめるというのは、以下のようなことをしたいということですか?それともまた別の意味? ========= 範囲チェックの過激なサンプル(笑) #include <iostream> struct RangeException {}; template<typename T> class RangeCheck { T lb, ub; public: RangeCheck(const T &lb_, const T &ub_) : lb(lb_), ub(ub_) {} const T &operator()(const T &v) const { if (v < lb || ub < v) throw RangeException(); return v; } }; struct X { int x; X(int x_) : x(x_) { std::cerr << "X(" << x << ")\n"; } ~X() { std::cerr << "~X(): " << x << '\n'; } }; struct Y { double y; Y(double y_) : y(y_) { std::cerr << "Y(" << y << ")\n"; } ~Y() { std::cerr << "~Y(): " << y << '\n'; } }; struct A { X x; Y y; static RangeCheck<int> check_x; static RangeCheck<double> check_y; void check() { check_x(x.x); check_y(y.y); } A(int x_, double y_) try : x(check_x(x_)), y(check_y(y_)) { std::cerr << "A(" << x_ << ", " << y_ << "): OK\n"; } catch (RangeException) { std::cerr << "A(" << x_ << ", " << y_ << "): NG\n"; } ~A() { std::cerr << "~A(): " << x.x << ", " << y.y << '\n'; } }; RangeCheck<int> A::check_x = RangeCheck<int>(0, 100); RangeCheck<double> A::check_y = RangeCheck<double>(-100, 0); void f(int x, double y, int z) try { A a(x, y); std::cerr << "construct OK\n"; a.x.x = z; a.check(); std::cerr << "check OK\n"; } catch (RangeException) { std::cerr << "catch exception\n"; } int main() { f(0, 0, 1); std::cerr << '\n'; f(10, -10, 1000); std::cerr << '\n'; f(-100, 0, 0); std::cerr << '\n'; f(0, 100, 0); } ===== % ./a.out X(0) Y(0) A(0, 0): OK construct OK check OK ~A(): 1, 0 ~Y(): 0 ~X(): 1 X(10) Y(-10) A(10, -10): OK construct OK ~A(): 1000, -10 ~Y(): -10 ~X(): 1000 catch exception A(-100, 0): NG catch exception X(0) ~X(): 0 A(0, 100): NG catch exception
お礼
お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。
- jacta
- ベストアンサー率26% (845/3158)
> 正当性チェック関数は10個用意しなければいけませんか? 普通は、コピーコンストラクタと代入演算子でまとめてチェックすればよいだけです。
お礼
お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。
- mikaemi
- ベストアンサー率50% (33/65)
型チェックはコンパイラにまかせればいいんじゃないですか?それとも、あるクラス階層の基底クラスのポインタなどの型のデータメンバを持っていて、そのメンバにはある派生クラスしかセットできないようにしたいとかですかね。。クラス階層のほうを修正できないんですかね?^^; データ範囲チェックなら、上限・下限の値をデータメンバとチェックメンバ関数を持つ、テンプレートで range クラスのようなものを作っておけばいいんじゃないですか?
お礼
お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。
お礼
お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。