• ベストアンサー

1 つのヘッダファイルに複数のクラスって?

C++ でコンソールアプリケーションを作っています。 プログラムの規模が大きくなり,クラスの数も増えてきました。 これまでヘッダファイルとクラスを一対一対応させてきました。 クラスの増加に伴い,ヘッダファイルがかなり増えてしまいました。 疑問に思ったのですが 1 つのヘッダファイルに記述するクラスの個数に,決まりはあるのでしょうか? ためしに 1 つのヘッダファイルに 2 つのクラスを書くと,問題なく動作しました。 ちなみに,その 2 つのクラスの関係は,お互いに完全に独立し合っている関係です。 (継承や friend の利用など一切なし,ということです。) 1 つのヘッダファイルに複数のクラスを書くことは OK なのでしょうか? またこうすることで生じる問題があれば,お聞かせいただければ幸いです。 (プログラミング超初心者につきマヌケな質問をしているかもしれません)

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

  • ベストアンサー
  • MrBan
  • ベストアンサー率53% (331/615)
回答No.2

言語に規制がないのは確かです。 Javaとかみたいに、publicがひとつとか、ファイル名とクラス名が一致してないとだめとかいうこともありません。 C++のファイルを分けるというのは、意味合い的には、 Javaとかでいうpackageわけ(ディレクトリ分け)にも近いものがあるので、 (実際には、論理構成とファイル構成が対応付けられてるJavaのpackageとは違い、 C++では翻訳単位の話と名前空間の話は別ですけど、前者的な観点でみて) 1クラス=1ヘッダというよりは、1パッケージ=1ヘッダの方が好ましいという考え方もあります。 # MFCなんかはボテッとしたクラスが基本なので、 # デフォルトで1クラス=1ヘッダを作ろうとしますけど…。 本当に、何の関係もないものをまとめるのは管理上もお勧めしませんが、 (実際の依存関係とは直接関係なく)意味的に関連のあるもの (同一パッケージに属するようなもの)はまとめてもありだと思います。 ほぼすべてが「1パッケージに1クラスづつしかない」ということは、 まともに設計されてればそうそうないと思いますので、 この程度の指針でもファイル数の削減は可能かと思います。

k1220011_2005
質問者

お礼

回答くださり,ありがとうございます。

その他の回答 (1)

  • galluda
  • ベストアンサー率35% (440/1242)
回答No.1

がると申します。 んっと…「言語仕様的な規則」は「ない」です。 ただ、可視性やら保守メンテナンスの観点からは…微妙になります。 曰く「ファイル数が多いと管理しきれない」 vs 曰く「1ファイルに複数クラスが書いてあると可視性が悪い」 どっちもどっちですねぇ。 個人的には ・原則として1ファイル1クラス ・ただし「極めて密接なもの」の場合複数クラスを1ファイルに書くこともあり ・ファイル名の前方一致で「近しいクラス」をまとめる というルーリングでやってますが。 まぁ「現場の流儀に従う」のが一番かもしれません。

k1220011_2005
質問者

お礼

回答くださり,ありがとうございます。 > ・原則として1ファイル1クラス > ・ただし「極めて密接なもの」の場合複数クラスを1ファイルに書くこともあり > ・ファイル名の前方一致で「近しいクラス」をまとめる 書物などを開いても,ヘッダファイルの「流儀」の記述は少なく,ここで質問してみてよかったです。 ファイル名なども考慮に入れれば,よりいっそう,管理しやすくなるというのは,参考になりました。

関連するQ&A

  • ヘッダファイルとソースファイルについて

    今までは、Webプログラミングを行っていたのですが、 最近になって、C++の仕事を請け負いましたので、 C++を勉強しつつ、プログラムをしていたのですが、 Webプログラムとの違いに悩んでいる部分があります。 それは、ヘッダファイルとソースファイルの関係についてです。 ほかのファイルから、インクルードされたヘッダファイルが、 読み込まれるというのは納得がいくのですが、 そのヘッダファイルに関連付け(?)られたソースファイルも、 一緒に読み込まれるという理由がわかりません。 ヘッダファイルでソースファイルを読んでいるような記述もないような感じなので、とても疑問に思っております。 なぜ、ヘッダファイルをインクルードしただけで、付属のソースファイルも読み込まれるのでしょうか?

  • ヘッダファイルに関数本体を書き込めないのか?

    こんにちは。 現在WindowsVistaでCおよびC++を使ってプログラミングを行っています。 最近になって思ったのですが、普通、ヘッダファイルに記述する内容は、 ・関数のプロトタイプ ・クラスのメンバ関数を除いた部分(いわゆる「クラスの骨格」) ・マクロ といったものだと言われています。 そして、関数の実態やクラスのメンバ関数などは、 別のソースファイルに記述するように言われています。 なぜ、ヘッダファイルに関数の実態や、クラスのメンバ関数を記述するべきではないでしょうか? あるいは、プログラムの内容に応じて、関数やクラスの内容を、 ヘッダファイルにまるごと記述してもよい場合と悪い場合があるのでしょうか? こういった事について、何か御存じの方がいらっしゃれば、是非アドバイスをお願い致します。 (難しい問題なので、なるべく詳しい説明を頂けると、大変助かります。) ちなみに、関数やクラスのメンバ関数も一緒に、クラスの内容をまるごとヘッダファイルに記述しても、 今までの所、全く問題なく動作しています。 例えば、以下のようなプログラムは、何の問題もなく動作します。 ●main.c ____________________________________________________________ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #include "func.h" void main(void) { char str[80]; puts("文字列を入力せよ"); gets(str); func(str); } ____________________________________________________________ ●func.h ____________________________________________________________ #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> void func(char *p) { puts("入力された内容は以下の通り。"); while(*p) putchar(*p++); } ____________________________________________________________

  • C++のヘッダーについて

    C++のプログラミングをしています そこで出てきた問題なのですが・・・ class Aのヘッダファイルa.hをほかのcppファイルにインクルードすると、 error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません error C2146: 構文エラー : ';' が、識別子 'test' の前に必要です。 とほかのヘッダファイルでコンパイルエラーがでます ヘッダファイルをインクルードしたときのみこのエラーがでて困っています。 解決法や、ヒントになりそうな事例を知りませんでしょうか?

  • c++でのヘッダーファイルの循環参照

     c++言語においての質問です.  A, Bという二つのクラスを作ったとします.  宣言は.h,実装は.cppで行っています. 【A.h】 class A{ //内容 public: B ConvertB(); }; 【B.h】 class B{ //内容 public: A ConvertA(); };  上のように,クラスAではクラスBを返すメソッド. クラスBではクラスAを返すメソッドを実装したいとします.  しかし,単純に 【A.h】に #include "B.h" 【B.h】に #include "A.h" などとすると当然循環参照になってエラーになりますよね? ...とは言っても, 【A.cpp】や【B.cpp】にインクルードした所で, ヘッダ側でエラーが起きてしまいます.  そこで,私の場合は... 【A.h】の先頭に class B{ConvertAで用いるメソッド}; 【B.h】の先頭に class A{ConvertBで用いるメソッド};  というようにする事でなんとかエラーを避けています.    ...しかし,この方法ではAやBのクラスの定義を修正する場合に, 2つのファイルのヘッダを書き換えなければならなくなります. A, B, C, D...などとクラスが増えていくと, 一つのヘッダーファイルに4つも5つもクラスの定義を書かなければなりませんし, クラスのメソッドの定義を一つ変えようとしただけでも, 複数のヘッダの内容をいじらないといけません.  非常に読みにくいコードになってしまうのです.  そこで,もう少しスマートに実現する方法は無いでしょうか?  JavaやC#を使えば簡単に解決するのですが...ライブラリの関係でC++を使わなければ ならないのです.  もしくは,このような相互変換?のクラスを作る場合はみなさんはどのようにして ヘッダーファイルの循環参照を避けているのでしょうか?  例えば様々な形式の色空間のクラスなどだったら... RGBクラス YCrCbクラス HSVクラス ...など  このようなクラスを作った後で,RGBをYCrCbに変換出来るようにしたり, その逆へも変換出来るようにしたいのです.  それともこのような変換が出来るクラスを作る事は間違っているのでしょうか?    よろしくお願いします.

  • 抽象クラスの継承について

    すいませんがご教授下さい。 ASP.NETとVB.NETを使用してアプリを開発しています。 存在するクラスは以下のようなクラスです。 (WebForm1.aspxとWebForm1.aspx.vbとClass1.vb(抽象クラス)があります。) したい事はClass1.vbをWebForm1.aspx.vbが継承したいのですが継承させた後にWebForm1.aspxを開こうとすると「Webフォームデザイナにファイルを読み込めませんでした。・・・・」とエラーポップアップが表示されます。「はい」でHTMLは見れるのですがデザインはタブ自体がないです。普通のクラスを継承させると問題ないのですが。抽象クラスだとエラーになります。 対処方を教えて下さい。

  • プログラムファイルの分割で…

    C++ でプログラムファイルを分割するとき,疑問に思うことがあります。 私はいつも,分割ファイルはヘッダファイルのみ用意しています。 関数の定義などすべてを,ヘッダファイルの中に書き込みます。 しかしキチンとしたプログラミングの本には   XXX.cpp   XXX.h と,二種類のファイルで分割ファイルを作成しています。 簡単なクラスしか作らないので,私は   XXX.h のみ用意して,簡単に使いたいのです。 私の方法でエラーなどが出たことはありませんが, 方法として,あまりオススメできないものなのでしょうか。

  • オブジェクト指向における「クラスA have a クラスB」の関係において,クラスBからクラスAのあるメンバ変数だけを触る方法

    クラス10~50個の中規模プログラミングに当たって,以下の問題がよく出てきて, 「簡潔な方法はないものか・・・」と悩んでいます. ●前提条件 【・「クラスAに持たれているクラスB( A have a B 関係)において,   クラスBからクラスAのあるメンバ変数(プロパティ)だけを触りたい」】 この場合,私はよく以下のようにしてしまい,クラス間の独立性を無くしてしまいます. ●方法1: ・クラスBのコンストラクタに「自分の持ち主であるクラスAのオブジェクト」を引数に取り,クラスBの変数(プロパティ)usedClassAとする. ======= C言語風に書くと, <code> public void クラスA{   クラスB usingClassB = new クラスB(); // 持っているクラスB   int commonNum = 0;   public void AddCommonNum(){       commonNum++;    }    ...    (その他の処理)    ... } public void クラスB{    class usedClassA;    // 持ち主のクラスA    // コンストラクタ    public クラスB(クラスA _usedClassA){        usedClassA = _usedClassA;    }    public void AddCommonNum(){        _usedClassA.AddCommonNum();    } } <\code> となります. この方法の問題点は,クラスAとクラスBに<双方向の依存関係を作っている>ことで, クラスAの設計(ここではAddCommonNum())が変更されたときに,クラスBの内容を変更しなければならない可能性があることから,拡張性に欠けると考えています. そこで,他に何かいい実装方法が無いか, 教えていただけないでしょうか? 特に,このような前提条件に汎用的に使える方法だと尚良いです.

  • HTTPヘッダーがどうしてもISO-8859になる

    Apache2.2.4(ソースからインストール)を使っています。 以下の問題は,IEなら問題ありません。すべてFirefoxで見る場合のみです。 HTTPヘッダーに 「Content-Type: text/html; charset=ISO-8859-1」が 入ってしまい,metaヘッダーにどんなcharsetを指定しても FirefoxがISO-8859と解釈して,文字化けを起こします。 httpd.confには, AddDefaultCharset ISO-8859の行はありません。 しかし, AddDefaultCharset UTF-8や AddDefaultCharset none と指定しても,ヘッダーにcharset=ISO-8859-1が表示されることには 変わりなく,問題解決しません。 .htaccessファイルは一切使っていません。 この問題はCGIに関係なく,任意のファイルで発生します。 一体,なぜISO-8859がヘッダーに現れるのでしょうか。

  • DLLからEXEのクラスを呼び出すとリンクエラーになります。

    私は昔VC++6.0を少し触っただけの初心者に近い状態のレベルです。 作っているプログラムは、1つのソリューションの中にEXE実行するプロジェクトとDLLを作るプロジェクトの2つプロジェクトを含んでいます。 DLL側からEXEのクラスを使用すると、ビルド時にリンクエラーになります。LNK2019でシンボルのエラーなのですが、なぜそうなのか?がわかりません。 ご教授いただけますでしょうか。 <ソリューションの構成> A ソリューション  Aプロジェクト(.exe) AAクラス ERR親クラス ← ERR子クラスの継承 Bプロジェクト(.dll) 静的リンク(.defファイル使用) BAクラス BAクラスの実装 {  try {   throw ERR子クラス } catch(ERR子クラス) { } } やりたいことは、BプロジェクトにあるERR子クラスをBプロジェクトと Cプロジェクトの両方で使用したいです。 ビルド時に上のBAクラスのERR子クラスのところでコンパイルはとおるのですが、リンクエラーになります。エラーコードはLNK2019です。 何が足りないのでしょうか? dllからexeのクラスを呼び出すようなことはできないのでしょうか? このやり方自体に問題があり、他の方法にする方がいいですか? ERR親クラス、ERR子クラスともヘッダー定義があり。 CAクラスのヘッダー定義内でinclude宣言しています。 versionはVC2003++です。 よろしくお願いします。

  • クラス構造をネストしたの宣言

    クラスA クラスB を使い、お互いに関連した構造にしたいのですが、宣言に困り質問させていただきました。 A.cpp ファイルは class A{ B b; }; のように、クラスB を含んだ状態です。クラスBもクラスAを含んだ状態です。 ここで、オブジェクトファイルを作成すべく、 $g++ -c A.cpp とすると、クラスBが宣言されておらず怒られてしまいます。 クラスBを先に宣言したり、ヘッダーファイルを作成しても、クラスBでもクラスAのオブジェクトを使っているので、やはり"定義されていない"とおこられてしまします。 C言語の関数を入籠にした場合は、プロトタイプを使用して問題を回避しましたが、クラスの場合でこれを解決する手段がわからず質問させていただきました。 どうかご教授ください。

専門家に質問してみよう