トップ回答者
ヘッダファイルの使い分け

質問
-
お世話になります。
プログラムを書いていたらやたらと長くなってしまったので、プロジェクトにヘッダファイルを2個追加し、それぞれのヘッダファイルに
・データを読み込むプログラム・・・・ヘッダファイル1
・データを処理するプログラム・・・・ヘッダファイル2
を書こうと思いました。データを読み込むプログラムの方に適当なクラスを作ってインスタンスを作成し、そこにデータを保存するところまではうまくいったのですがヘッダファイル2に書いたプログラムからヘッダファイル1のインスタンスのデータを読むことが出来ません。
データ処理の部分もヘッダファイル1に書けば処理上は問題ないのですが、かっこわるいので出来ればヘッダファイル2に書ければと思っています。
よろしくお願いします。
回答
-
「同じプロジェクト内の処理」のことを「プログラム」と呼ぶ人はいません。異なる名称を使われると他者とコミュニケーションできなくなりますよ。
# EXE / DLL / LIBなど「プログラム」という言葉から想像可能なものの場合に対する質問の解決方法と、「同じプログラム内の処理」に対する解決方法は異なると思い、確認しました。C++言語に限らずC言語時代から脈々と受け継がれている思想に「宣言と定義」という考え方があります。C言語・C++言語共に、宣言がされていれば定義されていなくてもそのクラス・関数を呼び出すことができます。ただし、実行ファイルを作成する段階で、宣言されかつ使われた全てのクラス・関数が定義されていないとリンクエラーになります。
仲澤@失業者さんの書かれた「農家.h」はクラスの宣言と同時に定義を行っています。これは
class 農家{ public: // 宣言 int 収穫します(箱& ミカン箱 , const CString& 畑名称); } // 定義 int 農家::収穫します(箱& ミカン箱 , const CString& 畑名称){ ・・・ }
と分けて書くことができます。その上で、定義は一般的に.cppファイルに記述しますし、.cppファイルは複数用意しても構いません。定義と宣言が理解できていれば、やたら長くなることはありません。
- 回答としてマーク ハードボイルド探偵 2011年11月29日 7:22
すべての返信
-
言葉足らずでもうしわけありません。m(_ _;)m
ヘッダーファイル2でにinclude"ヘッダファイル1.h"と記述してあるので、先にヘッダーファイル1を読み込み、その後ヘッダファイル2を読み込む形式になってるだろうと思います。それぞれのファイルに書いてあるのは処理に必要なクラスと関数です。先にクラスを作っておき、コンストラクタでインスタンスを作成し、関数内でデータを取得しています。データを読み込むことが出来ないと判断した理由は、ヘッダーファイル2に記述した関数内に置いてインテリセンスに表示されない、また、手書きしてもコンパイラを通らないといった理由です。
-
てきとうなクラスを書いたり、インスタンスがヘッダーにあったりしたらだめでしょうね(^^)。
ミカンの集荷作業ならこんな感じかもしれません。
<箱.h>
class 箱{ };<農家.h>
#include <箱.h>
class 農家{ public int 収穫します(箱& ミカン箱 , const CString& 畑名称){・・・}};<職員.h>
#include <箱.h>
class 職員{ public void 選別します(箱& ミカン箱, int 個数){・・・}};<集果センター.cpp>
#include<農家.h>
#include<職員.h>void 集果センター::ミカン収穫選別作業()
{
箱 ミカン箱;農家 太郎君;
int 個数 = 太郎君.収穫します( ミカン箱, "裏山");職員 花子さん;
花子さん.選別します( ミカン箱, 個数);
} -
「同じプロジェクト内の処理」のことを「プログラム」と呼ぶ人はいません。異なる名称を使われると他者とコミュニケーションできなくなりますよ。
# EXE / DLL / LIBなど「プログラム」という言葉から想像可能なものの場合に対する質問の解決方法と、「同じプログラム内の処理」に対する解決方法は異なると思い、確認しました。C++言語に限らずC言語時代から脈々と受け継がれている思想に「宣言と定義」という考え方があります。C言語・C++言語共に、宣言がされていれば定義されていなくてもそのクラス・関数を呼び出すことができます。ただし、実行ファイルを作成する段階で、宣言されかつ使われた全てのクラス・関数が定義されていないとリンクエラーになります。
仲澤@失業者さんの書かれた「農家.h」はクラスの宣言と同時に定義を行っています。これは
class 農家{ public: // 宣言 int 収穫します(箱& ミカン箱 , const CString& 畑名称); } // 定義 int 農家::収穫します(箱& ミカン箱 , const CString& 畑名称){ ・・・ }
と分けて書くことができます。その上で、定義は一般的に.cppファイルに記述しますし、.cppファイルは複数用意しても構いません。定義と宣言が理解できていれば、やたら長くなることはありません。
- 回答としてマーク ハードボイルド探偵 2011年11月29日 7:22
-
「ソースが長いからソースを分けたい」とか「かっこわるいからヘッダー ファイルを分けたい」とか、ちょっと本末転倒な気がします。
意味的に 1 つであるべきものとか 1 つのクラスであるべきものであれば、無理に分ける必要はないと思います。
この機会に「リファクタリング」を学んでみてはいかがでしょうか?
ヘッダー ファイルを読めているか読めていないかが分からないようですが、そういう場合はコンパイラ オプションでプリプロセッサ出力を書き出すと一目瞭然です。
/P (プリプロセス出力のファイルへの書き込み) (C++)
http://msdn.microsoft.com/ja-jp/library/8z9z0bx6.aspx
自分が作ったコードがどうコンパイルされているか把握できていないのは、別の問題として。 -
-
以前にもコメントしましたが、C言語やC++言語がわかってからC++/CLIに手を出すべきと思います。宣言と定義についてもC言語で習得すべき知識です。