• ベストアンサー

多くのファイルで共通で使う数(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は長すぎて難しいです)。 よろしくお願いいたします。

  • R-gray
  • お礼率41% (1005/2413)

質問者が選んだベストアンサー

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.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; } のような感じ.

R-gray
質問者

お礼

ありがとうございます。ようやく仰ることが理解できました! なるほど参照の一つの使い方が分かった気がします. この方法が一番コストパフォーマンスが良さそうなので 今回はこれでやってみようと思います. Tacosanさま及び回答してくださった皆さん、本当に有難うございました!

その他の回答 (4)

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

手堅くいくなら、 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&にキャストされて強引に書き換えられるのは避けられませんが、かなりましなはずです。

R-gray
質問者

お礼

詳しい解説ありがとうございます。 確かに手堅くて安善ですね.今後の参考にさせていただきます。 ありがとうございました!

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.3

一応、そういう目的に使える機能はあります。 const_castを使ってconst変数に代入する機能です。 参考URL http://www.s34.co.jp/cpptechdoc/article/newcast/ 本質的に安全になっているかどうかは非常に疑問なんですけど。

参考URL:
http://www.s34.co.jp/cpptechdoc/article/newcast/
R-gray
質問者

お礼

こんなキャストがあるのですね、ただ確かに危険な技ですね. でも頭にいれておきます.ありがとうございました。

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.2

要するに、実行のたびに値を変えて与えたいパラメーターが2つある、ってことですか。 だとすると、書かれているように argc, argv に取り込んで、 argv[] に入っている文字列を DIMENSION や ROOP(LOOP のこと?)の 数値に変換してやればよいです。

R-gray
質問者

お礼

そのとおりです。 つまり、 実行した直後にそのようにargvからDIMENSIONやROOP(すみませんそうですLOOPです^^;) の値を設定して、 その後は一切変更できないようにロックしてしまいたい! ということです。つまりプログラムの実行中に途中から ある変数にconstの効果をかけたい、ということです。 こういうことって可能でしょうか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

例えば, ヘッダの方で extern const int &DIMENSION; とかやって, 実際に変数を定義するソースファイルの方で int DIMENSION_def = 3; const int &DIMENSION = DIMENSION_def; っていうのはできないんでしたっけ? これができれば, 値の変更を関数経由に限定できるので簡単になるかと思います.

R-gray
質問者

お礼

ちょっと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()より「前」と「中」のギャップにちょっと困っている感じです。 もしそれも解決可能ならばもう少し詳しく教えていただけると助かります。 よろしくお願いいたします。

関連するQ&A

  • static と externについて

    以下のようなプログラムを組んでいます。 //main.h static int hoge; void someOperation(); //hoge.cpp #include "main.h" extern int hoge; void someOperation() { hoge = 15; } //main.cpp #include <stdio.h> #include "main.h" extern int hoge; int main() { someOperation(); printf("%d\n",hoge); return 0; } このプログラムを実行したのですが、自分の予想した15という出力ではなく、不定値になるようなのです。 自分の予想では、someOperationで操作するhogeも、main内で操作するhogeも同じになるようにと思いexternをつけているのですが、なにがまずいのでしょうか? ご存知の方、ご教授お願いします。

  • 複数ファイルによる共通の外部変数定義について

    初歩的な質問なのですが、今各関数をファイルごとに分けて記述しようとしています。 ここで詰まっているのでできればご教授お願いします ファイル構成は プログラムファイル main.cpp sub.cpp ヘッダーファイル  myheader.h(main.cppとsub.cpp両方でインクルード) ヘッダーファイルには両方のプログラムファイルで使う変数が定義してあります。 それでmain.cppとsub.cpp両方で同じ変数を使いたいのですがコンパイルエラーが発生してしまいます。 内容はsub.obj側で「i(共通のループカウンタ)はmain.objですでに定義されています」というものです。 とにかく私のやりたいことはヘッダーに外部変数を定義して両方のプログラムファイルで使いたいというものです。 もしかしたらファイルを分けるにも何か設定が必要なのでしょうか? 私はただ[プロジェクト]→[プロジェクトに追加]→[新規作成]でソースファイルを作っているだけなんですが・・・ 上記の状態を回避する方法はあるのでしょうか?

  • C++ クラスの作り方

    Windows10の上で、Visual Studio Community2015 を使ってC++を勉強中の者です。 Time クラスというのを定義して使おうとしましたが、クライアント側のプログラム作成中にエラーメッセージが出てきて、色々考えましたがどこが悪いのかわかりません。 プログラム自体は時刻を設定してそれを表示させるだけのものです。 詳しい方がいらっしゃいましたら、ご教授お願い致します。 問題のエラーメッセージ; "consoleApplication69.cpp" を作成中にエディターの中で、波型の赤線が出ているところにカーソルを持っていくと、次の3か所でそれぞれ次のようなエラーメッセージが出てきます。 (1) #include "time3.h" のところ: 「ソースファイルをひらけません。"time3.h"」 (2) 関数 incrementMinute( )のプロトタイプのところ:「不完全な型は使用できません。」 (3) 最初のパラメーター Time & のところ:「識別子 Time が定義されていません。」 以下に、 1: 私が作ったTimeクラスの定義のあるヘッダー "time3.h", 2: メンバー関数の定義ファイル "time3.cpp" 3:クライアント側プログラム "consoleApplication69.cpp" の3つのソースコードをコピーします。 "time3.cpp" については長いので、上の半分だけにしました。 ****************************************************** 1: "time3.h" ******************************************************** #pragma once // header file for Time class // time3.h #ifndef TIME3_H #define TIME3_H class Time { public: Time(int = 0, int = 0, int = 0); ~Time(); void setTime(int, int, int); void setHour(int); void setMinute(int); void setSecond(int); int getHour(); int getMinute(); int getSecond(); void printUniversal(); void printStandard(); private: int hour; int minute; int second; }; #endif *********************************************** 2: "time3.cpp" ************************************************ #include <iostream> #include <iomanip> #include <cstdlib> #include <ctime> #include <cmath> #include <cstring> #include "time3.h" using namespace System; using namespace std; Time::Time(int hr, int min, int sec) { setTime(hr, min, sec); } void Time::setTime(int hr, int min, int sec) { setHour(hr); setMinute(min); setSecond(sec); } void Time::setHour(int hr) { hour = (0 <= hr && hr <= 23) ? hr : 0; } void Time::setMinute(int min) { minute = (0 <= min && min <= 59) ? min : 0; } void Time::setSecond(int sec) { second = (0 <= sec && sec <= 59) ? sec : 0; } ********************************************************* 3: "consoleApplication69.cpp" ********************************************************* // ConsoleApplication69.cpp : メイン プロジェクト ファイルです。 #include "stdafx.h" #include <iostream> #include <iomanip> #include "time3.h" using namespace System; using namespace std; //prototype void incrementMinute(Time &, const int); int main() { Time t; t.setHour(2); t.setMinute(10); t.setSecond(30); cout << " current time is "; cout << setfill('0'); cout << setw(2) << t.getHour() << ":"; cout << setw(2) << t.getMinute() << ":"; cout << setw(2) << t.getSecond() << "\n"; return 0; } // function void incrementMinute(Time &tt, const int num) { // まだ未定義 } またソリューションエクスプローラーの画面写真も添付します。 ヘッダーファイルもインクルードしていますし、ソリューションの中に入れたつもりですが、なぜ Time が定義されていないといわれるのでしょうか? どうぞよろしくお願いいたします。

  • C++のファイル分割でのエラーについて

    最近VC2008でC++の勉強を始めたのですが、ファイル分割でLNK2005エラーというのが発生し、解消できません。 インクルードガードは行ったのですが、どうしたらよいのか分かりません。 ソースコードはこんな感じです。 //main.cpp #include "sub.h" #include "res.h" bool main(){ calcx(m_x); calcy(m_y); } //res.h 共有変数の宣言 #ifndef __RES_H #define __RES_H int m_x; int m_y; #endif //sub.h 関数のプロトタイプ宣言を行う void calcx(); void calcy(); //sub.cpp 関数の定義を記述する #include "res.h" void calcx(int x){ m_x = x + 100; } void calcy(int y){ m_y = y + 200; } エラー: 1>Main.obj : error LNK2005: "int m_x" (?m_x@@3HA) は既に sub.obj で定義されています。 1>Main.obj : error LNK2005: "int m_y" (?m_y@@3HA) は既に sub.obj で定義されています。 上記のようなエラーを解消するにはどうしたら良いのでしょうか。 何がおかしいのか指摘をお願いします。

  • 【VS2008 C++】2つのプロジェクト間で共通の関数を使いたい

    【VS2008 C++】2つのプロジェクト間で共通の関数を使いたい WindowsXP上で visual studio 2008 C++ express editionを 使用しています。 1つのソリューションに2つのプロジェクトをつくり、 その2つに共通の関数を使用させたいのですが、どのように 設定すればよいか教えて頂けませんでしょうか。 ソースの内容は以下のとおりです。 具体的には、mainB.cppでcommon.cppの関数を 呼び出したいです。 //common.cpp #include <stdio.h> void showCommon(){ printf("---common-----\n"); } //common.h #include<stdio.h> void showCommon(); //mainA.cpp #include<stdio.h> #include "common.h" void main(){ printf("---mainA-----\n"); showCommon(); } //mainB.cpp #include<stdio.h> #include "common.h" void main(){ printf("---mainB-----\n"); showCommon(); }

  • C++のファイルの分割について教えてください。

    分割したプログラムの書き方を練習中なのですが、 下のようなプログラムを書いて、ビルドしようとしたら失敗します。 どこが悪いのか、教えていただけないでしょうか? (5)\test30\Debug\test30.exe : fatal error LNK1120: 外部参照 1 が未解決です。 1>test30 - エラー 2、警告 0 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== //test30.cpp #include <iostream> #include "sub.h" int main(void) { std::cout<<"メインプログラムです。"<<std::endl; sub1(); sub2(); return 0; } ------------------------------------------------------------- //sub1.cpp #include <iostream> void sub1(void) { std::cout<<"サブ1です。"<<std::endl; } ------------------------------------------------------------- //sub2.cpp #include <iostream> void sub1(void) { std::cout<<"サブ2です。"<<std::endl; } --------------------------------------------------------------- //sub.h void sub1(void); void sub2(void);

  • JSPでCのようにヘッダーファイルをインクルード

    JSPでCのようにヘッダーファイルをインクルード お世話になります。 JSPでウェブページを作成しています。 ページ読み込み部分で前のページからPOSTされた情報に対して、 条件式を使い「真」ならそのページを表示、 偽の場合にはresponse.sendRedirect("URL");で別ページへジャンプをさせようと考えています。 その際に条件の判定に定数を使用したいのですが、 その定数は他のページでも使用する場合があるため、 C言語のヘッダーファイルのように、 別ファイルを用意して使い回しをしたいのですが… //test.h----------------------------- #pragma once const int CHECK_NUM = 15; //----------------------------------- //test.c #include <stdio.h> #include "test.h" int main(){ int n = 10; if(n < CHECK_NUM){ //真 } else{ //偽 } return 0; } このようにすればC言語では外部にかかれた定数を使用することができると思うのですが JSP,JAVAともに未経験のため詰まっています。(目下勉強中です) JSPで同様のことをするにはどのようにしたらよいのか教えていただきたいです。 質問をするにあたり情報の不足などがあるかもしれません。 その際にはお手数ですが、解答にてご指摘いただけると助かります。 宜しくお願い致します。

    • ベストアンサー
    • Java
  • 別のファイルの値を得るには?

    ファイルを分割して関数を別のファイルにおいたのですが値を返してもらおうとしても帰ってきません どのようにしたら関数の値を得られますか? 大体このような感じですね ---main.cppの内容--- #include <stdio.h> #include "betu.h" void main( void ){ printf( "%d" , a ); } ---betu.hの内容--- static int a; void betu( void ); ---betu.cppの内容--- void betu( void ){ a = 5; }

  • extern記憶クラス指定子を使う事について

    prg1.cpp----------------------------- #include<stdio.h> void func(void); int gg=5678; int main(void) { printf("main gg=%d\n",gg); func(); return 0; } ---------------------------------- prg2.cpp-------------------------- #include<stdio.h> extern int gg; void func(void) { printf("func gg=%d\n",gg); } ---------------------------------- 以上「prg1.cpp」と「prg2.cpp」という名前のふたつのファイルを作成し、「prg1.cpp」で宣言したグローバル変数を「prg2.cpp」で利用可能にしたいと思っています。 それには、「prg1.cppをコンパイルし、prg2.cppもコンパイルして、両者のオブジェクト(コンパイル後のファイル)をリンクする」と参考書には書いてあったのですが、どのようにしたらリンクされるのかわかりません。 prg.1cpp---------------------- #include<stdio.h> void func(void); int gg=5678; int main(void) { printf("main gg=%d\n",gg); func(); return 0; } #include<stdio.h> extern int gg; void func(void) { printf("func gg=%d\n",gg); } ------------------------------- 以上のように、「prg1.cpp」のファイルに1つにまとめれば、なぜかよくわかりませんが実行できました。 しかし「prg1.cpp」と、「prg2.cpp」をリンクさせてみたいので、教えていただけると嬉しいです。

  • namespace名前空間をヘッダファイル間で共用したい

    環境: WinXP, VisualStudio2005 目的: 現在WinAPI系のライブラリを作っているのですが、以下のような 状況で、namespaceを.cppファイルだけでなく.hファイルでも共用 出来るようにすることは可能でしょうか? ちなみに以下のコードでは lib.h(5) : error C2653: 'G' : 識別子がクラス名でも名前空間名でもありません。 lib.h(5) : error C2065: 'A' : 定義されていない識別子です。 というエラーが出てきます。 // main.h ---------------------------------------------------- #include "Global.h" int main() { } // Global.h --------------------------------------------------- #pragma once #include "Lib.h" namespace G { const int A = 100; } // Lib.h ------------------------------------------------------- #pragma once #include "Global.h" int b = G::A; //名前空間Gの中にあるAを代入

専門家に質問してみよう