
ある処理をするクラス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で質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
既定のコンストラクタがありま...
-
(void)0 はどんな意味ですか
-
多重定義が起きている?--lnk20...
-
C++にてtemplateで受け取った任...
-
戻り値を返す関数の前に(void)...
-
C/C++でのScene管理について
-
C# Controls.Addで動的に配置し...
-
Notepad++の関数リスト表示の変...
-
Arduinoでコンパイルエラーにつ...
-
typedef unsigned int UINT;が...
-
マルチメディアタイマーの使用方法
-
FortranからCの関数を呼ぶ方法
-
DLLの関数呼び出しで引数がある...
-
shared_ptrからpimplのデストラ...
-
静的でないメンバ関数の呼び出...
-
PIC16F819
-
【gcc・cygwin】multiple defin...
-
「Aに対するBの割合」と「Aに対...
-
Aの値からBの値を除するとは??
-
20'(角度)の計算がわかりま...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
静的でないメンバ関数の呼び出...
-
既定のコンストラクタがありま...
-
C++にてtemplateで受け取った任...
-
多重定義が起きている?--lnk20...
-
【gcc・cygwin】multiple defin...
-
const_castのつかいどころを教...
-
戻り値を返す関数の前に(void)...
-
C言語 ① 5秒間 1秒間隔で点滅を...
-
C# Controls.Addで動的に配置し...
-
C#でテンキーの操作は可能でし...
-
int main()、void main()、void...
-
C# KeyDownイベントでショート...
-
gcc: incompatible pointer type
-
Notepad++の関数リスト表示の変...
-
(void)0 はどんな意味ですか
-
VC++でGetKeyboardStateがうま...
-
関数ポインタについて
-
void main()って誰が最初?:AN...
-
演算子のオーバーロードでコン...
-
この式の意味
おすすめ情報