ある処理をするクラスAとログ出力のような動作をするクラスBがあります。
Bクラスはメイン処理及びメインから呼ばれたクラスA両方から呼ばれます。
メイン処理にて、Bクラスのコンストラクタで出力ファイルのパスを指定し
その情報をメインから呼ばれたAクラスの中で呼ばれるBでも使用したいと思っています。
クラスを引数として渡せば可能かもしれませんが、できればその方法は使いたくありません。
何か良い方法はありませんでしょうか?
void main()
{
B clsB("c:\\aaa.txt")
A clsA;
clsA.fnc();
}
A::fnc()
{
clsB.output();
}
//Class B.h ---------
class B {
private:
char path[256];
public:
B(char *buff);
int fnc();
};
//Class B.cpp ---------
B::B(char *buff)
{
strcpy(path, buff);
}
B::output()
{
fp = fopen(path, "a");
・・・
}
No.2ベストアンサー
- 回答日時:
ポインタや参照として、引数として渡すのはスタンダードな方法ですが
その場合でも、渡す回数や関数呼び出し回数等は最小限で済むように、カプセル化を十分強めておくことが
大変有効です。
それを踏まえたうえで、別の方法も色々とあります。
方法1.
B clsB("c:\\aaa.txt")
A clsA;
この順番で確実に作るのでしたら、こういうのも考えられます。
class B; //前方宣言
class A {
const B* const b; //ポインタ(や参照)を持たせる
public:
A( const B* b_ ) : b(b_) {}
void fnc() const;
};
//ソース
void A::fnc() const { b->output(); }
方法2.
もしAとBが意味的に十分強い関係性を持ち、セットに出来るようなケースでは、方法1のように別々に作ってからポインタを受け渡したりせずに、AがBの生成と破棄を管理してもいいでしょう。
方法3.
Bがログ出力専用のようなクラスで、一つだけなど、特定の個数あれば十分な場合
自分自身にstaticな方法でインスタンスを管理させて、どこからでもstatic関数で呼び出せるようにする
といった方法も考えられます。
class B {
static B* b; //生成されるインスタンス格納用
char path[256];
B( const char* ); //コンストラクタを始め、staticでないメンバはすべてprivateでもOK
void output() const;
public:
static void Init( const char* c ){ b = new B(c); }
static void Cleanup(){ delete b; b = NULL; }
static void output_S(){ if (b) b->output(); }
};
あとはソースに
B* B::b( NULL );
とでも書いておきます。
これで、最初の方に
B clsB("c:\\aaa.txt")
のかわりに
B::Init( "c:\\aaa.txt" );
としておき
後は引数として渡さなくてもどこからでも
B::output_S();
だけで呼び出せます。
そして終了前に解放します。
B::Cleanup();
方法4.
とりあえず、引数でやるけど
クラス数がB,C,D…と増えるといった場合
別に構造体等を作っておいて、それだけいじれば済んでしまう、という形にしてしまうのもいいでしょう。
例
class B;
class C;
class A {
public:
void ABC( const B&, const C& );
void ABC2( const B&, const C& );
void ABC3( const B&, const C& );
};
ここにDを単純に加える場合
class B;
class C;
class D;
class A {
public:
void ABC( const B&, const C&, const D& );
void ABC2( const B&, const C&, const D& );
void ABC3( const B&, const C&, const D& );
};
こうなってしまう、というのであれば
stuct DATA {
const B* b;
const C* c;
};
とかを別途作っといて
struct DATA;
class A {
public:
void ABC( const DATA& );
void ABC2( const DATA& );
void ABC3( const DATA& );
};
などとしておくことで、このDATA構造体を書き変えるだけで
stuct DATA {
const B* b;
const C* c;
};
↓
stuct DATA {
const B* b;
const C* c;
const D* d;
};
同様の効果が得られます。
No.3
- 回答日時:
おそらくは、クラスを使うべきではないところで無理やりクラスを使おうとしています。
クラスというのは、たんなる関数の寄せ集めではなくて、ある程度の自律性を持った機能の集合です。
で、一番自然な使い方は、複数のインスタンスを生成して、それぞれのインスタンスごとの振る舞いを行わせるということです。
だから、ログをとるというクラスがあれば、いろいろなログを独立してとる(それぞれに独立したインスタンスが存在する)のであれば、有効です。
一方で、一連のログ(早い話が、ログファイルファイっこしかない)をあちこちで収集するなら、「一連のログをとる」関数郡をひとまとめにすれば言いいのです。
C++には、namespace という機能があって、そういう用途にも使えますから、
logFiles::init(char *filePathName); で最初にログファイルを設定して、
logFiles::appendNormal(char *message); で、正常なログを追記して、
logFiles::appendError(char *message); でエラーログを追記して
のようなこともできます。
また、本当に、処理のあちこちで、いろいろなログをとりたいのなら、「このログファイルへの追記」というのがそれぞれ明確でしょうから、「このログファイル」を指定するために、クラスのインスタンスを渡すべきです(というか、インスタンスを渡すのではなくて、「該当するログを担当しているインスタンスに、ログをとるようにメッセージを送信する」という考え方が、正解)
No.1
- 回答日時:
普通は「クラス (のインスタンス) を引数として渡す」ものなんだけど....
むしろ, どうして「その方法は使いたくありません」と思ったのでしょうか?
この回答への補足
Tacosanさん回答ありがとうございます。
>どうして「その方法は使いたくありません」と思ったのでしょうか?
あくまで予定ではあるのですが
例えばクラスAの複数の関数で呼ぶなどとなった場合や
クラスCが追加になった場合など、すべてに引数として渡すのは
どうかなと思ったので、ほかの方法があるならそっちの方がいいのかな
と考えたからです。
(そもそもコンストラクタなどでファイルパスを指定するのが正しいのか
よくわかっていないこともありますが・・・)
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- その他(プログラミング・Web制作) Pythonで複数のメソッドをまとめて管理する方法について 1 2023/03/30 00:01
- Java java 次の機能を有するメソッドを自クラスに作成し、実装したいです。 機能 名前判定機能 →名前が 3 2022/06/16 16:08
- Java javaのクラスの分け方について質問です。 APIの内部用と外部用でクラスを分けたいのですがインター 2 2022/04/26 16:06
- Java java final 1 2022/06/10 22:49
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- PHP アップロード画像数でCSSを分けることに成功したのですが、画像の横に文字を並べることが出来ません。 3 2023/07/28 17:16
- Java javaの質問です 次の機能を有するメソッド4つを自クラスに作成し、実装したいです 【機能】 足し算 1 2022/06/15 17:49
- その他(プログラミング・Web制作) どういうプログラムで組みますか?google colabでやってるんですけど、出来る方お願いします。 1 2022/07/06 09:28
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Notepad++の関数リスト表示の変...
-
既定のコンストラクタがありま...
-
ArduinoでMouse関数を使用して...
-
【gcc・cygwin】multiple defin...
-
解凍ソフト(C++builderで作成...
-
解凍ソフト(C++builderで作成...
-
int main()、void main()、void...
-
【VC++6.0】イベントハンドラ関...
-
C言語 int main(void) main()
-
C++別のオブジェクトからメンバ...
-
C# Controls.Addで動的に配置し...
-
C で、関数の中から、別の関数...
-
コールバックって・・・
-
定義した文字列を wchar_t 系の...
-
一定時間ごとにプログラムを起...
-
2÷3などの余りについて
-
C言語で%を使わない余りの出し方
-
比較回数と交換回数表示について
-
信頼区間の1.96や1.65ってどこ...
-
nCmの関数
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
【gcc・cygwin】multiple defin...
-
int main()、void main()、void...
-
戻り値を返す関数の前に(void)...
-
既定のコンストラクタがありま...
-
Notepad++の関数リスト表示の変...
-
ArduinoでMouse関数を使用して...
-
多重定義が起きている?--lnk20...
-
C++にてtemplateで受け取った任...
-
静的でないメンバ関数の呼び出...
-
C# Controls.Addで動的に配置し...
-
const_castのつかいどころを教...
-
(void)0 はどんな意味ですか
-
C# KeyDownイベントでショート...
-
gcc: incompatible pointer type
-
C#でラジオボタンを設定に記録...
-
VC++でGetKeyboardStateがうま...
-
C言語 ① 5秒間 1秒間隔で点滅を...
-
void*型の配列について
-
GDI+の使用方法について
-
DirectInput でのエラー
おすすめ情報