• ベストアンサー

includeファイルの読み込み追加の際のコインパイルエラー

VC初心者で初めて質問させて頂きます。 仕事でVC++6.0にて開発を行っています。 既設で正常に動作しているプロジェクトに対して ロジックを追加しなければいけないのですが、 その際、同プロジェクト内で定義されていない 変数を使用したく、includeファイルの 読み込みを追加(#include "aaa.h")し、参照しようと したのですが、以下のようなコンパイルエラーが 発生してしまいます。 '***' 定義されていない識別子です。 ***:追加したincludeファイル内にて定義されている    変数 紐付けがうまくいってないと思うのですが プロジェクトの設定画面にて、インクルードファイル のパスを確認したところ既設にてパスは存在して いました。 同様に依存関係を確認したところ、必要な ヘッダファイルは全てありました。 関係あるかはわかりませんが、クリーン→ビルド しても状況は変わりませんでした。 パスが通っているなら単純にインクルードファイルを 読みこんで参照すればいいと思うのですが、 何か他に必要なことがあるのでしょうか 初めての質問ということで、質問の仕方が 分かりづらい点もあるかと思いますが 宜しくお願い致します。

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

  • ベストアンサー
回答No.9

No.8 です。訂正。 大嘘ついてました。 > あと、CLS_bbb のメンバが protect: であったとしても、CLS_bbb *pbbb = pApp->ccc.pddd; が正しければ、pbbb-> の形でアクセスできます。 いえ、できません。できないのが正解です。 さて、このときに考え方は二つあります。 ・メンバーが protected: である以上、このメンバーを参照したくなるようなプログラムは設計的に間違っている。 ・設計的には間違っているが、特殊な事情があり、「掟破り」をしなければならない。 まず、いずれなのかを見極める必要があります。 その上で、「掟破り」の方法。 これは、派生クラスを作って、セッタやゲッタを定義するという方法があります。 たとえば、ベースクラスの int value が protected: の場合、これを参照すると。 class CLS_bbb_sub : public CLS_bbb { public: int get_value() { return value;} void set_value(int v) { value = v;} } これで、 // アプリケーションクラスのポインタを獲得 CLS_aaaApp *pApp = (CLS_aaaApp *)AfxGetApp(); CLS_bbb_sub *pbbb = dynamic_cast<CLS_bbb_sub *>(pApp->ccc.pddd); ここまで考えてみましたが、やっぱりだめのようですね。 上記雄 ccc.pddd が、CLS_bbb_sub だったら、これで対処できますが、実際には、違うクラスなのだから、上記の2行目で実行時エラーになりますね、きっと。 やはり、それは、アクセスしてはいけないメンバーなのでしょう。

kudamono10
質問者

お礼

返事が遅くなってしまいました。 回答ありがとうございます。 初心者である私にとって非常に分かりやすく説明してくださって 感謝しております。 おかげさまで問題は解決いたしました。 結論からいいますと >・メンバーが protected: である以上、このメンバーを参照したくな>るようなプログラムは設計的に間違っている。 ご指摘の通り設計的に誤っておりました。 考えてみれば、特にprotectedなメンバ関数などを他のプロジェクト のクラスから使用するなんておかしいですよね 調査したところロジックを追加するクラスのインクルードにて 同様なprotectedなメンバ変数・関数が用意されており、 それらを使用すればよいというなんともがっくりな おちでした。 では改めてありがとうございました。

その他の回答 (8)

回答No.8

残念ながらこれ以上は、クラス相互の関係がわからないと何とも言い難いです。 ただ、インクルードファイルにあるのは多くの場合、単なる定義です。 その実体は、それをインクルードしているファイルのどこかで定義されています。 ですから(単なる言葉の間違いかもしれませんが)インクルードファイルに定義してある変数を参照するというのは普通ありません。 このあたりが、理解の鍵になるかもしれません。 あと、 // アプリケーションクラスのポインタを獲得 > CLS_aaaApp *pApp = (CLS_aaaApp *)AfxGetApp(); > CLS_bbb *pbbb = pApp->ccc.pddd; ですが、AfxGetApp() の返値をわざわざ (CLS_aaaApp *) にキャスとしているのが不自然です。敢えてこうしたというのであれば、おそらく、AfxGetApp() の返すポインタは、CLS_aaaApp のサブクラスかベースクラスかどちらかのポインタかなと思います。 もしも、CLS_aaaApp のほうがサブクラスであれば、dynamic_cast というのを使ってみてください。その方が安全にキャストできますし、サブクラスのポインタに正しく変換してくれたかなと思います。 あと、CLS_bbb のメンバが protect: であったとしても、CLS_bbb *pbbb = pApp->ccc.pddd; が正しければ、pbbb-> の形でアクセスできます。 どうも、継承がらみで、サブクラスからベースクラスへのキャストか、この逆かが発生していて、そのあたりの処理がうまくいっていない気はします。

回答No.7

直接回答していませんでした。 1点目 "aaa.h"の中で"bbb.h"を読み込んでおりさらに"bbb.h"の中で "ccc.h"を読み込んでいる場合において"ccc.h"内で定義されている 変数を使用したい場合"aaa.h"だけをプログラムで読み込んで、 直接変数名を指定して使用することは可能なのでしょうか (各ヘッダファイルの場所はプロジェクトが異なっていたりします) 可能です。 インクルードしたファイルに書かれていたのは、単に、「そう書かれていた」ように展開されるだけなので、 #include "ccc.h" の代わりに、同じところに ccc.h の中身を直接書いても同じことになります。 ただし、同じように ccc.h を取り込んでいるプロジェクトがある場合、ある日 ccc.h の内容が変更になったとします。 そのとき、この、「直接書いた」プロジェクトだけは、なぜか変更ができていなくて大騒ぎになったりすることがあるので、そのあたりの兼ね合いも必要です。

kudamono10
質問者

補足

回答ありがとうございます。 変数をグローバル化して、共通に使用するようにする方法 について大変勉強になりました。 ただ現状況といたしましては 既設のソース内のインクルードファイルで 定義されている変数の属性を変える事は避けたいと考えております。 (正常に動作しておりどこに影響を及ぼすかがはかりかねない為) できれば既設のインクルードファイルの定義は変えず使用したい のです。 調査を進めていたところ他のプロジェクトのヘッダファイルにて 定義されている変数を参照する方法だと思うのですが、 既設のソースにて以下の様な処理を行っていました。 // アプリケーションクラスのポインタを獲得 CLS_aaaApp *pApp = (CLS_aaaApp *)AfxGetApp(); CLS_bbb *pbbb = pApp->ccc.pddd; ※ここでCLS_bbbが参照したい変数のあるクラス このあと追加ロジックとして pbbb-><参照したい変数> と記述したところコンパイルエラーはでなくなりました。 一部解決はしたのですが新たな問題として CLS_bbbに定義されている変数がprotectedのものがあり、 コンパイルエラーとなってしまいました。 その後、CLS_bbbクラスのサブクラスとすればよいのではと 考え、ロジックを追加するプロジェクトのヘッダファイルにて 以下の様に継承させてみたのですが同様にコンパイルエラー となってしまいます。 ※protectedをpublicに変えるのはその変数がDBがらみの  アクセス変数ということもあり避けたい  影響もこわい;; class <ロジックを追加するクラス> : public CLS_bbb ^^^^^^^^^^^^^^^^ サブクラスと継承の概念が誤っているかもしれません。 クラスの構成上継承できないということなのかもしれません。 当初と質問の内容が変わっており申し訳ないのですが ご教示いただければありがたいです。 質問を再度まとめますと 他のプロジェクトのヘッダファイルに定義されている変数 を使用したい その変数値はその時点における最新値を参照したい 変数の属性や型の変更は避けたい

回答No.6

No.5 訂正です。 グローバル変数の管理のところ。 #if defined(GLOBAL_HERE) #define GLOBAL #define DEF(x) = (x) #else #define GLOBAL entern #define DEF(x) #endif です。 GLOBAL がひとつ抜けていました。 これで、 GLOBAL int iwork; GLOBAL int jwork DEF(1); と書かれた内容をインクルードすると以下のようになります。 #define GLOBAL_HERE #include "value.h" このとき、GLOBAL_HERE が定義されているので、 GLOBAL → (なにもなし) DEF(x) → = (x) と置換されます。 その結果、 int iwork; int jwork = (1); と展開されます。 #include "value.h" このとき、GLOBAL_HERE が定義されてないので、 GLOBAL → exntern DEF(x) → (なにもなし) と置換されます。 その結果、 extern int iwork; entern int jwork; と展開されます。

回答No.5

まず、2重インクルードの防止方法 これは、有名なテクニックです。 各インクルードファイルの先頭に #if !defined(HEAD_CHECK_AAA) #define HEAD_CHECK_AAA のような2行を入れます。 この、HEAD_CHECK_AAA は、2行で同じであり、他のヘッダファイルと重ならなければなんでもいいです。 そして、最後に #endif を入れます。 これで、同じファイルは実質的に1回しかインクルードされなくなります。 2番目。 まず、インクルードファイルの中で変数を定義しても、それは、単に、インクルードした場所にその記述がなされるだけです。 従って、インクルードファイルの中に int iwork; があったとしても、それを複数のふぃあるで別々にインクルードすると、それぞれ全く別の変数になります。 これを解決するためには、一緒にコンパイル(というか、本当はリンク)するファイルの1カ所で、 int iwork; と定義し、 その他の iwork を使いたい場所では、 extern int iwokr; という定義をします。 これは、変数の実体がどこにあるか、また、その変数をどこでいじっているかわかりにくくなるため、「グローバル変数の乱用」として、できれば避けるべきこととされています。 さて、上記のような事情ですが、 ・一カ所だけ変数定義 ・他の部分は extern をつける ・しかも宣言が異なっている(あるところは、 int あるところは char)とだめ というグローバル変数を統一的に管理する方法として、以下のようなテクニックがあります。 1)共通して読み込みヘッダファイルに以下のような記述をつけます。   たとえば、value.h とします。 #if defined(GLOBAL_HERE) #define GLOBAL #define DEF(x) = (x) #else #define entern #define DEF(x) #endif この後に、共通して使いたい変数を GLOBAL をつけて定義します。 GLOBAL int iwork; 初期値が必要な場合、 GLOBAL int jwoek DEF(1); のように書けます。 ここまでが、インクルードファイルの指定です。 あと、これを使うプログラムで、インクルードするわけですが、メインになるファイルだけ、 #define GLOBAL_HERE #include "value.h" のように、GLOBAL_HERE を define してからインクルードします。 それ以外のファイルでは、単純に(GLOBAL_HERE を定義せずに) #include "value.h" だけでインクルードします。 これで、 ・同じ型で ・一カ所だけ変数の定義があって ・他の部分は extern つき という宣言ができます。 しかも、もともとは、value.h というひとつのファイルなので、externつきとextern なしの変数の型が違っていたなんてこともありません。

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

/Pオプションを付けるなどして、プリプロセスだけを実行した結果を確認してみてください。 案外すぐに問題点が見つかるかもしれません。

回答No.3

とりあえず、「ミススペル」の可能性は当たってみた方が良いかもしれません。 または、aaa.h の中の、その部分だけ、コメントアウトされてしまっているとか、条件コンパイルで無視されるところにあるとか。

kudamono10
質問者

お礼

回答ありがとうございます。 >とりあえず、「ミススペル」の可能性は当たってみた方が良いかもしれません。 ミススペルは確認したところありませんでした。 >または、aaa.h の中の、その部分だけ、コメントアウトされてしまっているとか、条件コンパイルで無視されるところにあるとか。 前に回答してくださった方への補足に記載しましたが 新たにincludeファイルを追加する必要はなくなりましたが コンパイルエラーとなっております。

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

まず、 #include "aaa.h" と書かれている直前と直後に aaa(; のように「絶対にエラーになる文」を挿入してコンパイルしてみよう。 もし aaa(; があるにも関わらず「対応する括弧が閉じていない」と言うエラーが出なかったとしたら #include "aaa.h" の行は「コンパイルされず無視される位置」に書かれている。書く位置を変えよう。 同様に、aaa.hの中で「使いたい変数を定義している行の前後」に、同じように「絶対にエラーになる文」を挿入してコンパイルしてみよう。 同じように「対応する括弧が閉じていない」と言うエラーが出なかったとしたら「変数を定義している行は、コンパイルされず無視される位置」に書かれている。書く位置を変えよう。

kudamono10
質問者

補足

意見参考になりました。 ありがとうございます。 その後調査を進めたところ、既設のソースにて 該当includeファイルは読み込まれおり、2重定義を していました。 ネストがあったため気づきませんでした。 前の方の回答の補足に記載しましたが、 では単純に直接変数名を指定して使用する ということではないようです。 お教え頂けるとありがたく思います。

  • SAYKA
  • ベストアンサー率34% (944/2776)
回答No.1

そのincludeファイルの中で他のincludeの内容が関わる物が有るんじゃない? もしそうだとしたらincludeの順番とかでも出る出ないが変わるよ

kudamono10
質問者

補足

意見参考になりました。 ありがとうございます。 その後調査を進めたところ、既設のソースにて 該当includeファイルは読み込まれおり、2重定義を していました。 ネストがあったため気づきませんでした。 しかし再度コンパイルしたところ、同じエラーが発生しております。 これについて2点疑問に思いました。 1点目 "aaa.h"の中で"bbb.h"を読み込んでおりさらに"bbb.h"の中で "ccc.h"を読み込んでいる場合において"ccc.h"内で定義されている 変数を使用したい場合"aaa.h"だけをプログラムで読み込んで、 直接変数名を指定して使用することは可能なのでしょうか (各ヘッダファイルの場所はプロジェクトが異なっていたりします) ccc.h内の定義 int iwork; プログラム #include "aaa.h" ------------------- iwork = 2; ------------------- 2点目 他のプロジェクトで変数に値をセットしていて、 その変数値を参照する場合、includeファイルを読み込んで その変数を参照しても値はとれないように思えてきました。 よくわかっていない部分なのですが、クラス変数の引継ぎが 必要のように思います。 イメージ的にはもともと変数値をセットするところをたどって そのクラスから今回ロジックを追加するクラスまで変数を引き継ぐ ということなのですが、どうコーディングしていいか分かって おりません。 2点目については最初の質問から外れているかもしれませんが 宜しくお願い致します。 同一問題なのかわかっておりません。

関連するQ&A

  • VC++で、ソースファイルを追加すると、コンパイルエラーになります。

    こんばんは。 VC++6.0を使い、C言語の勉強をし始めました。新規プロジェクト→Win32 Console Application を作成し、簡単なプログラムを作成しています。 最初からあるソースファイルはコンパイル、実行できます。しかし、後から自分で追加したソースファイルは error C2065: 'printf' : 定義されていない識別子です。 という、エラーが出てしまいます。何かが、関連付けられていないのでしょうか?それとも、新規プロジェクトを作成しなければいけないのでしょうか? 私は、VC++が初めてなので、ぜんぜんわかりません。よろしくお願いします。

  • 自作インクルードファイル

    こんにちわ。 いまVC++6.0で開発しようとしています。 自作のincludeファイルを作成し,親プログラムをコンパイルしようと しますが,そのincludeファイルが親プログラムと同じパスに あるときはコンパイルできますが, 別のフォルダに置くと, fatal error C1083: インクルード ファイルがオープンできません。 'XXXXXX.H': No such file or directory cl.exe の実行エラー と出てしまいます。 そこで[設定]の"インクルードファイルのパス"の箇所を 自作インクルードファイルがある場所に設定したのですが, やはり同じエラーメッセージが出ます。 どうすれば読めるようにできるのでしょうか? 教えてください。 よろしくお願いします。

  • atlstr.hのインクルードによるエラーについて

    atlstr.hのインクルードにより生じるエラーについて質問させて頂きます。 開発環境は、Visual Studio 2008 Professional Editionです。 (Visual Studio 2008におけるプログラミングは正直まだ慣れておりませんorz) Visual Studio 2008製品内のVisual C++ 2008において、以下の操作を行いプログラムを 実行すると、コンパイルは通るのですが、プログラム実行後にエラー音が一度鳴るだけ でフォームが表示されないというエラーが発生します。その際、タスクマネージャでプロセ スを確認するとプログラム自体は動いているようで、”AtlStrTest.exe”というプロセスが実 行されているのが確認できます。 1.[ファイル]->[新規作成]->[プロジェクト]で新しいプロジェクトダイアログを表示させる 2.[Visual C++]->[CLR]->[Windows フォーム アプリケーション]を選択し、プロジェクト名   ”AtlStrTest”でプロジェクトを新規作成 3.プロジェクト内に生成された”atdafx.h”の”// TODO: プログラムに必要な追加ヘッダー   をここで参照してください。”というコメントの下に#include <atlstr.h>の一行を追加する  原因を分析しようにも、ヘッダをインクルードしただけでエラーが起きるという状況がは じめてなので、途方に暮れている状態です。 大変恐縮ですが、このatlstr.hのインクルードによるエラーがなぜ発生したのかについて、 どなたかアドバイスよろしくお願いいたします。 【関連情報】  同様の操作を、Win32コンソールアプリケーションで実行したときは、このようなエラーは 出ませんでした

  • VC++ includeファイルについて

    VC++2005でグローバル変数を利用したいと考えています。 そこで、kaisu.hというヘッダーファイルにint n=0;と書いてあります。 そこでプログラムでは、 #include "kaisu.h" しているのですが、エラーがどうしても出てしまいます。 エラーは以下の通りなのですがどのようにすれば良いのでしょうか? error LNK2005: "int n" (?n@@$$Q3HA) は既に Form2.obj で定義されています。 場所::試作品.obj エラー 2 fatal error LNK1169: 1 つ以上の複数回定義されているシンボルが見つかりました。

  • MFCのインクルードファイルについて

    VC++のMFCについて教えていただきたいのですが。 VC++のプロジェクトには、MFCとかコンソールアプリとかあると思うんですが、普通のWinアプリやコンソールアプリにはなく、MFCで標準的にインクルードされるファイルってどんなものがあるのでしょうか。 今、コンソールアプリでコンパイルしたらエラーとなり、MFCでするとエラーなくコンパイルできます。 よろしくお願いします。

  • VS2010追加のインクルードディレクトリについて

    ソリューションと同階層にソースファイルやヘッダーファイルを散乱させるのは汚いなと思い、フォルダに分けました。 例) .slnの階層     mainフォルダ        main.h        main.cpp     sampleフォルダ        sample.h        sample.cpp      abcdフォルダ        abcd.h        abcd.cpp      efghフォルダ        efgh.h        efgh.cpp するとヘッダーをインクルードする時にパスが増えてしまうのも嫌だなと思って、 プロパティ   C/C++     全般       追加のインクルードディレクトリー で作ったフォルダを全て指定しました。 そうしたら一応 main.cpp で #include "sample.h" だけで通るのですが いつも #include "s まで打つとsample.hが候補で出てきてたのですが出なくなってしまいました。 代わりに当然といえば当然ですが #include "sample/sample.h" は候補に出てきます。 追加のインクルードディレクトリーをしても 候補は直接出てくるようには出来ないのでしょうか? パスを全部書いてしまうと追加した意味がありません… これと同様の質問なのですが、 abcd.cpp で main.h をインクルードしたい時も 候補には出ず、../を打って出てくると思うのですが こちらも追加のインクルードディレクトリをしても直接出るようには出来ないのでしょうか? なにか変なことを言ってるような気がしてきましたが よろしければ教えて下さい。

  • VisualC++2005ExpressEditionBeta2にてインクルードファイルのディレクトリを登録したいのですが..

    「Visual C++ 2005 Express Edition Beta2」にて、[ツール] -> [オプション] -> プロジェクトおよびソリューション-> VC++ディレクトリ にある「ディレクトリを表示するプロジェクト」の中からインクルードファイルを選択しても何も反応がありません。 インクルードファイルのある場所を登録したいのですが、この方法では登録できないのでしょうか? よろしくお願いします。

  • コンパイルエラー「include ファイルを開けません」

    あるプログラムをコンパイルしたところ、 下記コンパイルエラーが発生しました。 ヘッダファイルが開けないようなのですが、 これは自分の開発環境に必要なファイルが足りないのでしょうか? 解決する方法が分からないので、ご存知の方おられましたら ご教示お願い致します。 環境はVC++2005でフルインストールしています。 fatal error C1083: include ファイルを開けません。'WtsApi32.h': No such file or directory

  • 【SSI】include file、include virtualが動作しない

    htmlはほぼマスターしているのですが、SSIは超初心者です。 標記の通り、include file、include virtualを試しているのですが、参照先のファイルが表示されません。サーバにはアップロードしておらず、ローカルで確認しているのですが、これでは動作しないのでしょうか。 --index.shtml <html> <head> </head> <body> <!--#include file="0000.html" --> ... <!--#include file="0001.html" --> </body> </html> --0000.html <html> <head> </head> <body> あああ </body> </html> 情けない質問ですが、よろしくお願いします。

    • ベストアンサー
    • HTML
  • 複数プロジェクトをビルドしたとき、DLLに新しく追加したClassのみがリンクエラーになる

    VC++6.0上で、複数の関連するプロジェクトをすべてビルドしたときのリンクエラーで悩んでいます。 現在、ワークスペースには、以下の複数のプロジェクトがあります。 ・Mainとなるプロジェクト ・上記のMainプロジェクトがDependしている、DLLのプロジェクト 問題は、DLLプロジェクトに新しいClassを追加したところ、単体でビルドすると成功するにもかかわらず、MainプロジェクトをActiveにしてリビルドしたときに、新しく追加したClassだけが下のように未解決にされてしまうということです。 ”error LNK2001: 外部シンボルXXX(追加したクラスのコンストラクタ)は未解決です” このClassはDLLの内部で使用されており、Mainプロジェクトから直接呼ばれるClassではありません。また、このClassの使用箇所をDLLのソースからコメントアウトすると、リンクエラーは解消されます。 VC++に不慣れかつ、他人の作ったプロジェクトなこともあり、現在の設定内容がいま一つわかっていないところがあります。問題はそのあたりだと思うのですが、はっきりしません・・・。 調べてわかっていることは、以下です。 ・Mainプロジェクトから呼ばれるDLLのHeaderファイルにはパスが通っている。 ・Mainプロジェクトから呼ばれるDLLのLibraryにはパスが通っている。また、#pragmaによりリンクされている。 ・Mainプロジェクトから呼ばれるDLLにはパスが通っている。 ここを確認してみたらどうか?など、ヒントをもらえたらありがたいです。 よろしくお願いいたします。

専門家に質問してみよう