- ベストアンサー
多くのファイルで共通で使う数(C++)
現在大学の卒業研究でこんな感じのプログラムをC++で作っているのですが ちょっと行き詰っています。 動くには動くのですが、汚いというか。 main.cpp --->実験プログラムのメイン。実験の初期値などが書いてある。 basic.cpp --->基本的な算術計算につかう関数やデータ構造のクラスが書いてある。 sampling.cpp learning.cpp --->実験にいろいろ使うメソッドが書いてある。 これらに加えてbasic.h, sampling.h, learning.hがあり それぞれのcppファイルにインクルードしてあります。 また各cppファイルに共通で使う定数があるのです。たとえば const int DIMENSION = 3; //3というのはたとえばで実験の条件による違う const int ROOP = 20000; などという感じです。これをmain.cppの先頭で宣言して condition.hにextern const int DIMENSION;などと書いて 各cppファイルにこれまたインクルードさせてあります。 今のところこれはこれでプログラムは問題なく動いているのですが 今になって仕様を少し変更する必要が出てきました。 たとえばこのcppファイル群をzikkouという実行ファイルに コンパイルしていたとすると、実行の際に $ zikkou 4 20000 という感じに引数としてDIMENSION,ROOPの値を指定したいのです。 ($はプロンプト画面、ターミナル画面ということです) constのままだとこのように実行の毎にDIMENSION,ROOPを変更するというのは出来ないと思うんですが constを外すと、実行中の安全性が疑問です。 (これらの定数は一回ある値でプログラムが動き出したら絶対に 変わりませんし変わってはいけません) なにか良い方法はございませんでしょうか? よろしくお願いいたします。 なにか情報不足がありましたらおっしゃってください。 すぐに補足いたします(ソースのupは長すぎて難しいです)。 よろしくお願いいたします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
#4 も同じですが, 要するに「実際に値を持っている変数」と「値を参照するために使う変数」を分けましょう, ってことです. #4 の例でいえば, 「最初に (一度だけ) 値を設定する」ときには変数 dimension の値を変更し, それ以降の「値を参照する」ときには変数 DIMENSION を参照します. そうすれば, 基本的にソースはほぼそのまま使える (再コンパイルは必要ですが) ことになります. dimension を変更するときにはそれ用の関数を使うことにより, 二重設定などもチェックすることができます. extern const int & を使うなら vars.h: extern const int &DIMENSION: void setDimension(int dim); vars.cpp: #include "vars.h" namespace { int dimension; } const int &DIMENSION = dimension; void setDimension(int dim) { dimension = dim; } main.cpp: #include "vars.h" #include <cstdio> int main(int argc, char *argv[]) { setDimension(3); // ここは適切に std::printf("%d\n", DIMENSION); return 0; } のような感じ.
その他の回答 (4)
- jacta
- ベストアンサー率26% (845/3158)
手堅くいくなら、 class const_int { const int& value_; public: explicit const_int(const int& value) : value_(value) {} operator int() const { return value_; } }; namespace { int dimension; } const const_int DIMENSION(dimension); のように、クラスを介すのがよいでしょう。 これなら、const_castを使って値を強引に書き換えられる心配もありません。 reinterpret_castでint&にキャストされて強引に書き換えられるのは避けられませんが、かなりましなはずです。
お礼
詳しい解説ありがとうございます。 確かに手堅くて安善ですね.今後の参考にさせていただきます。 ありがとうございました!
- rinkun
- ベストアンサー率44% (706/1571)
一応、そういう目的に使える機能はあります。 const_castを使ってconst変数に代入する機能です。 参考URL http://www.s34.co.jp/cpptechdoc/article/newcast/ 本質的に安全になっているかどうかは非常に疑問なんですけど。
お礼
こんなキャストがあるのですね、ただ確かに危険な技ですね. でも頭にいれておきます.ありがとうございました。
- asuncion
- ベストアンサー率33% (2127/6289)
要するに、実行のたびに値を変えて与えたいパラメーターが2つある、ってことですか。 だとすると、書かれているように argc, argv に取り込んで、 argv[] に入っている文字列を DIMENSION や ROOP(LOOP のこと?)の 数値に変換してやればよいです。
お礼
そのとおりです。 つまり、 実行した直後にそのようにargvからDIMENSIONやROOP(すみませんそうですLOOPです^^;) の値を設定して、 その後は一切変更できないようにロックしてしまいたい! ということです。つまりプログラムの実行中に途中から ある変数にconstの効果をかけたい、ということです。 こういうことって可能でしょうか?
- Tacosan
- ベストアンサー率23% (3656/15482)
例えば, ヘッダの方で extern const int &DIMENSION; とかやって, 実際に変数を定義するソースファイルの方で int DIMENSION_def = 3; const int &DIMENSION = DIMENSION_def; っていうのはできないんでしたっけ? これができれば, 値の変更を関数経由に限定できるので簡単になるかと思います.
お礼
ちょっとTocosan様がおっしゃってくれている方法をきっちり理解していないのですが、 const int xxxxというのは main.cppのなかで先頭、というか int main(int argc, char* argv[]){}よりも 上 で 宣 言 さ れ て なければならないと思うのですが 実行の際にzikkou 4 20000などと指定した引数を取り入れてアレコレやるのは int main(int argc, char* argv[])の中だと思います。 (argv[1] = "4", argv[2]="20000"なので) そのint main()より「前」と「中」のギャップにちょっと困っている感じです。 もしそれも解決可能ならばもう少し詳しく教えていただけると助かります。 よろしくお願いいたします。
お礼
ありがとうございます。ようやく仰ることが理解できました! なるほど参照の一つの使い方が分かった気がします. この方法が一番コストパフォーマンスが良さそうなので 今回はこれでやってみようと思います. Tacosanさま及び回答してくださった皆さん、本当に有難うございました!