コンストラクタの引数を関数で算出したい

[戻る]
ろっく 2004/07/04(日) 23:42:07
こんばんは。基礎的すぎる質問なのかもしれませんが、どうしてもわからないので・・
VC++6.0を使用しています。

あるデータ処理をするクラス(クラス名:DATA)をC++で作成しました。
(このクラスはコンソール上では問題なく動作します)
これをConsole Application でなく、AppWizard で使いたいと思っています。

まずAppWizerd(exe)でスケルトンを作成し、
グローバルな位置にDATA data()と宣言し、
他のファイルからはexternでdataにアクセスすればいいと思うのですが、
コンストラクタへ渡す引数が関数で求めた値である場合はどうすればいいでしょうか?

今回の例では、渡す引数が確保したファイルポインタとなっており、
Console Application の場合ならメイン関数の中で
FILE* fp;
fp = fopen("a.txt","r");
DATA data(fp);
のように宣言すれば全く問題ないのですが、
AppWizard の場合はグローバルな位置に宣言するため、fopen関数が使えません。

何かいい方法があるのでしょうか?
以上、おわかりの方がおられましたらアドバイスの方をよろしくお願い致します。

シャノン 2004/07/05(月) 00:25:07
クラスそのものではなくポインタを宣言しておいて、ファイルを開いてから new で作る
ときにファイルポインタを渡すとか。
グローバルにすること自体があまりよろしくありませんが…。

monkey 2004/07/05(月) 01:38:16
できればグローバルにしない方が良いというのは、シャノンさんと同意見。

どうしてもグローバルにしなければならないのであれば、DATAクラスにデフォルトコン
ストラクタとファイルポインタを渡すメンバ関数を追加する方法もあります。
例えば:

class DATA
{
    FILE* fp_;
public:
    DATA( FILE* fp ) : fp_( fp ){}
    DATA() : fp_( 0 ){}                 // 追加
    void setfp( FILE* fp ){ fp_ = fp; } // 追加
    ...
};

アプリケーションの方では、グローバルで

DATA data;

と定義しておき、ファイルを開くところで

    FILE* fp;
    fp = fopen("a.txt","r");
    data.setfp( fp );

とする。
繰り返しますが、できることならグローバルにはしたくない。

PATIO 2004/07/05(月) 11:05:15
うーむ。
MFCを使われるのであれば、
そのアプリがSDI、MDIなのか、ダイアログベースなのかとか、
ドキュメント・ビュー・アーキテクチャを使うのかによって変わってきますが、
皆さんが言われているようにカプセル化の概念から行けば、グローバルに置くのは
どうかなと言う気がしますね。C++的にはなるべくグローバルにインスタンスを
おくようなことはしない方向で考えると思います。
これをやってしまうとDataクラスを使用する側のクラスの独立性が損なわれますからね。

データクラスにデフォルトコンストラクタで作成しない事に意味があって
そういうつくりにしているのであれば、シャノンさんの案だと思います。
逆にデフォルトコンストラクタで作っていない事に意味が無いのであれば、
monkeyさんの案のようにデフォルトコンストラクタで生成しておいて、
別途、初期化用の関数を使って設定できるようにもしておく方が自由度は高いですね。

グローバルに出すぐらいなら、
なんらかのクラスのメンバー変数とかにするのが本当では?
そのクラスがなんになるのかはそのアプリの構造によるので一概には言えませんけど。

ろっく 2004/07/05(月) 22:19:25
みなさん、さっそくのレスをありがとうございます。
大変参考になります。
これで目的のソフトを作ることができそうです。

ただ、3人の方が口をそろえてグローバルが悪いとおっしゃるので、
何とかそういう形にしていきたいと思います。
そこで改めて質問させていただきたいのですが、
DATA data; とグローバルで宣言しようと思った理由は、
ダイヤログからの値入力を可能としたいからです。
(ちなみにMDIに挑戦しており、ドキュメントクラスは使用しない予定です)

データ追加用のダイヤログを作成しクラスウィザードを使うと、
Add.h Add.cppといったファイルにCAdd といった名前のクラスが自動生成されますよね?
ダイヤログから入力した値をAdd.cppのOnOK関数内で構造体に格納し、
その構造体を引数としてdata内のメンバ変数に格納する、といった処理を予定していま
す。

このようなダイヤログは複数あり、ビュークラスからもdataの内容は見たいわけです。
ならばどのファイルからもdataにアクセスするためには、
結局グローバルで持たなければならないのか?と考えたわけですが・・・

少々長くなってしまいましたが、仕様に誤りがあればご指摘ください。
よろしくお願い致します。

επιστημη [E-Mail] [HomePage] 2004/07/06(火) 09:31:14
>(ちなみにMDIに挑戦しており、ドキュメントクラスは使用しない予定です)

何故にDocumentを使わないのでしょう?

> このようなダイヤログは複数あり、ビュークラスからもdataの内容は見たいわけです。
> ならばどのファイルからもdataにアクセスするためには、

Documentがデータを持つのがよさげに思えますが。

PATIO 2004/07/06(火) 09:41:50
私的にはドキュメント・ビュー・アーキテクチャと言うのは良く出来た仕組みだと
思います。ドキュメントとビューを別立てにすることで表示とデータ管理を切り離せる
からです。
多分、クラスの独立性を考慮してクラス構成を考えると結果的にはDoc-Viewに近い構造に
なると思います。
επιστημηさんも言われているようになぜ使わないのかを説明すれば、
良いアドバイスが得られかもしれません。

PATIO 2004/07/06(火) 09:47:28
ちなみにドキュメントクラスにデータを置いておけば、
ViewからはGetDocumentでポインタが取得できますし、
ダイアログはViewから表示されるでしょうから
GetDocumentで取り出したポインタを引き渡せば、
どうとでもなります。

私自身がダイアログを使うときは、そのダイアログには、データレコードを一つ分だけ
渡すようにしてダイアログがデータ全体を受け取るようにはしないと思います。
ダイアログはダイアログで閉じた世界にしたいのでなるべくデータ構造全体が
ダイアログに影響を与えないように考えます。

古いスレッドには追加発言できません。