• 締切済み

個々のデータの正当性チェックの関数について教えて下さい

クラスの中に10個メンバ変数があるとします。それぞれのメンバ変数にデータを代入する時に、そのデータの正当性をチェックする関数をクラス内に作るとします。10個のメンバ変数は各々正当である値の型や範囲が異なるんで、正当性チェック関数は10個用意しなければいけませんか? それとも、テンプレートなぞを使えば1個の関数にできるのでしょうか? 最もよく使うような方法を教えて下さい。 正当性チェックの内容は、型チェックとデータ範囲くらいです。

  • aneja
  • お礼率93% (379/405)

みんなの回答

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.4

補足: たとえば、今、ご自分で作成されているプログラムのコードを貼り付けて、こういうことをしたいと具体的に書いておけば、jacta さんも、「普通は、…よいだけです。」という、つれない回答ではなく、具体的なサンプルのようなものを提示してくれてたのかもしれませんから^^

aneja
質問者

お礼

お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.3

「さぁ~て、いい回答は出てるかな。。。」という感じで、何日か後にまとめて見るのでしょうが、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

aneja
質問者

お礼

お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

> 正当性チェック関数は10個用意しなければいけませんか? 普通は、コピーコンストラクタと代入演算子でまとめてチェックすればよいだけです。

aneja
質問者

お礼

お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。

  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.1

型チェックはコンパイラにまかせればいいんじゃないですか?それとも、あるクラス階層の基底クラスのポインタなどの型のデータメンバを持っていて、そのメンバにはある派生クラスしかセットできないようにしたいとかですかね。。クラス階層のほうを修正できないんですかね?^^; データ範囲チェックなら、上限・下限の値をデータメンバとチェックメンバ関数を持つ、テンプレートで range クラスのようなものを作っておけばいいんじゃないですか?

aneja
質問者

お礼

お礼が遅くなりまして、申し訳ありませんでした。早速のご回答、ありがとうございました。この画面を毎日チェックする暇もなくなり、申し訳ありませんが、暇ができたら頂いたご回答をゆっくり検討いたします。失礼で勝手なことを言いまして、申し訳ありません。どうもありがとうございました。

関連するQ&A

  • Γ関数に虚数単位(√-1)を代入したときの値を教えてください

    Γ関数に実数を独立変数として代入する場合は勉強した範囲でわかるのですが、解析接続して変数を複素数に拡張したときの値の求め方が難しくてわかりません。 そこで、具体的に虚数単位である√-1を代入したときのΓ関数の値の求め方、およびその値を教えていただけると、複素平面上に展開されたΓ関数をイメージしやすく、かつ、学びやすいと思いました。 どなたか教えて頂けると幸いです。

  • クラスについての質問

    私はゲームを作っています。作り始めのころクラスの存在を知らずに めちゃくちゃに組んでいたのですが、最近になってクラスを使わないと 不便だという事に気が付きました。現在クラスを使用して修正中です。 クラスについて調べている時に、クラスの中のメンバの値を変える時は そのクラスの中でしか変えてはいけない、ととあるサイトで見かけました。 更にクラスのメンバはなるべくpublicで宣言してはいけないとも見かけました。 そこで気になったのですが、クラスの中のメンバの値をクラス外の 変数やクラスのメンバ等に代入したい時はどのようにすれば良いのでしょうか? クラス外でメンバを参照するにはpublicで宣言しなければなりませんし、 クラス内に変数をアドレスで引き渡して代入してしまうと、クラス内でしか 値を変えてはいけないということを守れなくなってしまいます。 このような場合はどのようにして値を代入すれば良いのでしょうか? 返答をお願いします!。

  • メンバー関数ポインタ

    非常に基礎的なことで申し訳ないですが。 クラスのメンバー関数へのポインタ変数へ 代入しようとすると 関数呼び出しには引数リストがありません。 とエラーがでます。 何がわるいでしょうか? 以下のような感じのコードです。 void (classname::*P_func)() = classname::func; 定義しただけと思いますが。。 VCです。 よろしくお願いします。

  • DLOOKUP関数について

    お世話になっております。 現在ACCESS2000を使用しております。 テキストボックスのコントロールソースにDLOOKUP関数を使用しております。 DLOOKUPで抽出して値(数値)を変数(Integer)に代入しております。 そこで何故か代入出来る値と出来ない値があり困っております。 デバックで確認するとDLOOKUPでは値を持ってこれておりますが 変数に代入する際に失敗しているようです。 何故そのような事象が起こるのか調べてもわからず質問させていただきます。 恐れ入りますが、心当たりあるかた、どうか教えて頂けませんでしょうか。 以上、よろしくお願い致します。

  • 関数に値の代入 [C言語]

    C言語初心者です。関数とポインタについて勉強していたのですが、ふと関数の型を知りたくなってVC++で型を調べてみたんです。そしたら、void型で引数のない関数の型は void (__cdecl*)() となっていました。voidと__cdeclはわかります。 そしてこれ型に*が入ってるじゃないですか。ということは関数はポインタということになると思います。なので私はもしかしたら値の代入ができるのではないか、と思ったのです。早速、 f1=f2;(f1とf2は型と内容の同じ関数) や、 (*f1)=(*f2); としてポインタの中身や参照先の関数の実態の値を処理中に書き換えてみようとしました。ですが、多分そうなるとは思ったのですが、コンパイルエラーが出ました。 《エラーの内容》 error C2106:'=':左のオペランドが、左辺値になっていません。 warning C4550:式は引数リストのない関数として評価します。 関数を書き換えようとすること自体馬鹿げていることは重々承知です。でも、微かにいけそうな気がするんですよ。代入させたくないなら関数の型は一律constにすると思うし(実際関数をconstをつけて宣言してもOKだった、(プロトタイプ有り無しでも))、関数への代入は問答無用で駄目なのならばそういうエラーメッセージを出すと思うんです。 関数の書き換えは100%無理でしょうか?それとも関数を書き換える方法があるでしょうか?回答よろしくお願いします。

  • 【再確認】C言語のcharとvarcharの扱い

    すみません、前回も似たような質問をしましたが、再確認させてください。 例えば、変数1はサイズが256、型がvarchar、値がabcで、変数2はサイズが20、型がcharの場合、 変数1から変数2には値を直接代入できますか? また、代入できた場合、変数2の値はabc+スペース17桁になりますか? 逆に変数2の値がabcの場合、変数2から変数1には直接代入できますか? また、代入できた場合、変数2の値はabc(後ろにスペース等なし)になりますか?

  • 配列 x に入っているデータの個数を求める関数の作り方

    配列 x に入っているデータのうちで、値が正(つまり x(i) .gt. 0.0d0 ) であるデータの個数を求める関数 numpos(x,n) を作り方を教えてください。n はデータの個数。 implicit real*8(a-h,o-z) real*8 x(1000) dummy = rand(13) 乱数の初期化 n = 1000 do 10 i=1,n x(i) = rand(0)-0.4d0 テストデータ 10 continue write(6,*) 'numpos =', numpos(x,n) stop end function numpos(x,n) implicit real*8(a-h,o-z) real*8 x(*) この部分が分かりません。(関数副プログラムなので、関数の値、つまり正のデータの個数は、関数名と同じ名前の変数、つまり numpos という名前の変数へ代入すること、らしいです。) return end とても困っていますし、急いでいます。 誰か助けてください。 よろしくお願いします。

  • メンバ関数テンプレートの仮想関数。

    VC8.0言語処理系でメンバ関数テンプレートを仮想関数にしたらエラーになりました。 これは、VC8.0言語処理系の対応なのでしょうか? それともC++言語系の仕様なのでしょうか? 今回、メンバ関数の一部にイテレータを使用していまして、その関係で一部の関数がテンプレートになっています。 そして、基底クラスでは実装せず、派生先で実装を強制する純粋仮想関数としたのですが、この処理がコンパイルエラーとなっています。 メンバ関数の参照などを考えたのですが、どうも巧くコンパイルでき無そうです。 この処理が出来ないことは設計段階で把握していなかったので、これが出来ないとすると設計のし直し(テンプレートの廃止など)をしなくてはいけません。 詳しい方がいらっしゃいましたら、お願いします。

  • 【C++】メンバ変数をポインタで宣言するデメリット

    クラスAが、メンバーとして、 クラスXと、クラスYを持っているとします。 そのようなとき、 【ケース1】  クラスAを定義する際、  メンバである、クラスX、クラスYは、ポインタで宣言させる。 【ケース2】  クラスAを定義する際、  メンバである、クラスX、クラスYは、ポインタではなく、クラスX/クラスYの型として宣言させる。 があると思いますが、それぞれどのようなデメリットがあるでしょうか? ----------------------------- 私は、ケース1は、 メリット:   クラスXを継承したクラスChild_Xや、クラスYを継承したクラスChild_Yを、   クラスAで扱えるようになる。   デメリット:   クラスXのポインタで宣言していると、クラスXを派生したクラスが格納可能であるため、   開発時に、そのメンバーに、実際にはどの型のクラスが格納されているかがわからず、   Visual Studio で追いかけられない。   (※そのメンバーに対して、右クリック⇒定義で見ても、どの型のポインタ変数かはわかっても、     どの型がそこに突っ込まれているかは、代入されているところを探して確認しないとわからない。) 私は、処理を確認する際、『どの型の値がそこに突っ込まれているかは、代入されているところを探して確認しないとわからない。』というのが、可読性は悪いわ、確認に時間が取られるわで、 非常に大きなデメリットと考えています。 このデメリットを解消する方法はあるのでしょうか?

  • 複数クラスで共通の関数、変数の呼び出し方

    お世話になります。 質問させて頂きたいことは 複数のクラスで共通して使われる関数、変数があった場合、その関数、変数は私の中で次の2通りの方法が思い当たったのですがどちらのほうがメモリ等の使用からよいのでしょうか? 1つめは あるヘッダファイル****.hを作成し、その中で関数を宣言し、変数はそのヘッダファイルのソースファイル中のグローバル変数とする。 2つめは クラスを作成し、静的メンバ関数、静的メンバ変数とする。 ネット等で拝見すると、あまりグローバル変数というのはよく見られていないようなので2つめの方がいいのかなと思っているのですが、静的メンバを今まで使ったことがないので、このような用途に使われるべきなのかも正直わかっていません。 検討外れのことを言っているのかもしれませんが、教えて頂ければと思っております。宜しくお願い致します。

専門家に質問してみよう