はじめまして
今MFCのダイアログベースでプログラムを書いています。
この中でさまざまな処理の過程でのデータを格納したり
取り出したりする為の データクラスをクラスの種類Generic
でを作りました。
このクラスをプログラムが動いている間常に実体化しておいて、
他のクラスからデータのGetやSetをしたいと考えています。
単体試験のレベルでは関数の中でこのクラスを実体化してれば
いいのですが、結合や総合試験では当然ながら、その関数が
終われば実体化されたものは開放されてしまいますので、
データのやり取りができません。
C++の時は main関数 でこのようなデータクラスは実体化して
データのやり取りをしていましたがVC++ では main関数はない
ので、どこで実体化したらよいか分りません。
このようなケースでよく処理をする方、知っている方がいましたら
教えて下さい。
よろしくお願い致します。
下記に自分で作ったデータクラスを明記しておきます。
//ヘッダーファイル
class CPartsData
{
private:
char machine[_MAX_PATH];
char cereal[_MAX_PATH];
char version[_MAX_PATH];
char fdPath[_MAX_PATH];
char sudPath[_MAX_PATH];
char ldPath[_MAX_PATH];
char sdPath[_MAX_PATH];
public:
CPartsData();
virtual ~CPartsData();
void GetData(CDataBox &DB);
void SetData(CDataBox &DB);
};
//cppファイル
//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////
CPartsData::CPartsData()
{
}
CPartsData::~CPartsData()
{
}
//////////////////////////////////////////////////////////////////////
// データ取得
//////////////////////////////////////////////////////////////////////
void CPartsData::GetData(CDataBox &DB)
{
strcpy(DB.machine, machine);
strcpy(DB.cereal, cereal);
strcpy(DB.version, version);
strcpy(DB.fdPath, fdPath);
strcpy(DB.sudPath, sudPath);
strcpy(DB.ldPath, ldPath);
strcpy(DB.sdPath, sdPath);
}
//////////////////////////////////////////////////////////////////////
// データセット
//////////////////////////////////////////////////////////////////////
void CPartsData::SetData(CDataBox &DB)
{
strcpy(machine, DB.machine);
strcpy(cereal, DB.cereal);
strcpy(version, DB.version);
strcpy(fdPath, DB.fdPath);
strcpy(sudPath, DB.sudPath);
strcpy(ldPath, DB.ldPath);
strcpy(sdPath, DB.sdPath);
}
CMy(プロジェクト名)Appというクラスが、CMy(プロジェクト名)App.hにありませんか?
そのクラスのメンバにすれば、たしか、プログラムの実行中は常に存在したと思いますが。
#単純にグローバルなオブジェクトにするとか・・・
CMy(プロジェクト名)Appのメンバにしたとき
その変数をどのように使うかは、下記のサイトを参考にしてみてください。
どこでグローバルな変数を定義するか /* 頼もしい仲間AfxGetAppたち */
http://www.hi-ho.ne.jp/hawk/mfc0401.html#whereval
KING・王さんありがとうございます。
上手くいかなかったのでもう少し教えて下さい。
きっと下のクラスだとおもうのですが、CPartsData このクラスのメンバーに
追加しました所メンバーPDができましたので AutoMationApp.h を
(プロジェクト名)Dlg にインクルードしたら
fatal error C1083: インクルード ファイルがオープンできません。'AutoMationApp.h ': No such
file or directory
とエラーがでました。
もちろんインクルードしない場合は
error C2065: 'PD' : 定義されていない識別子です。
とエラーがでます。
やり方がおかしいのでしょうか?アドバイスよろしくお願い致します。
下記はデータクラスを追加したAPPのソースです
////////////////////////////////////////////////////////////////////////////
// CAutoMationApp:
// このクラスの動作の定義に関しては AutoMation.cpp ファイルを参照してください。
//
class CAutoMationApp : public CWinApp
{
public:
CAutoMationApp();
//ここでデータクラスを実体化
CPartsData PD;
// オーバーライド
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CAutoMationApp)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL
// インプリメンテーション
//{{AFX_MSG(CAutoMationApp)
// メモ - ClassWizard はこの位置にメンバ関数を追加または削除
します。
// この位置に生成されるコードを編集しないでください。
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
本当にAutoMationApp.hってファイルがありますか?
単に (プロジェクト名).h に AutoMationAppのクラスがないですか?
エラーメッセージの内容を読めばわかると思いますが、
写し間違いでないのであれば、AutoMationApp.hなんてファイルはないと言ってます。
コンパイラが無いと言っているわけなので疑う余地も無くないはずです。
通常ならAutoMationDlg.cppと同じフォルダー内にAutoMationApp.hもあると思いますが、
ないですか?
まずはそこから確認しましょう。
エラーが出ても直ぐに聞くのではなくてある程度調べて見て自分なりの結論は出した方が
いいです。
調べたのであれば、きちんと調べた内容を書いてください。
掲示板では書かれていない内容はやっていないとみなされて仕方ありません。
あと、「error C2065: 'PD' : 定義されていない識別子です。」というメッセージは
どのファイルをコンパイル中に出ていますか?
AutoMationDlg.cppをコンパイルしている時なのであれば、これ以前にCAutoMationAppが
未定義と言われそうですけれど。
あと、AutoMationApp.hにCPartsDataを追加したのであれば、
CPartsDataのヘッダファイルをAutoMationApp.hにインクルードしておかないと
そもそもコンパイルが通らないと思いますが、その点は大丈夫ですか?
Blueさん・PATIOさんありがとうございます。
確かにBlueさんの言うとおり、AutoMationApp.h は無いのですが、 VC++ には
ヘッダーファイルが無いのが多いので、Windowsがそのファイルを認識している
ものと思っい、#include AutoMationApp.h としてしまいました。
PATIOさんにご指摘されてる点については AutoMationApp.h は存在しません。
コンパイルしているのはAutoMationDlg.cppですが CAutoMationAppが未定義
とエラーはでません。
CPartsDataのヘッダファイルを AutoMation.h にインクルードしています。
この件に関しては AUTOMATION アプリケーションのメイン ヘッダー ファイルです。
とうたっているので問題はないと認識しています。
これらも踏まえて今調査中ですが、またアドバイスがありましたら、お願い致します。
> VC++ にはヘッダーファイルが無いのが多いので、
んなバカな。
> 確かにBlueさんの言うとおり、AutoMationApp.h は無いのですが、 VC++ には
> ヘッダーファイルが無いのが多いので、Windowsがそのファイルを認識している
> ものと思っい、#include AutoMationApp.h としてしまいました。
その認識は間違っています。
無いファイルをインクルードなどと言うことは断じてありえません。
それは多分、ピースケさんが見つける事ができなかったというだけで
きちんと存在しています。
あと、ファイル名がAutoMationApp.hというのは間違いでAutoMation.hが正しいですね。
えーと、多分ですが、
いきなりCAutoMationDlgクラスの関数の中で単にPDと書いてアクセスしようとしてませんか?
そもそもPDはCAutoMationAppクラスのメンバーなのでPDとだけ書いてもアクセスできません。
これはC++言語では常識的な話なのでこれがわからないのであれば、
MFCを使ったプログラミングの勉強する前にC++言語の勉強をした方がいいです。
もし、CAutoMationDlgクラスの関数の中で使いたいのであれば、
dynamic_cast<CAutoMationApp*>(AfxGetApp())->PDとか
reinterpret_cast<CAutoMationApp*>(AfxGetApp())->PDしてください。
単に、CPartsDataクラスのメンバをstaticにするんじゃダメですか?
まぁ、インスタンスが2つ以上必要になったら破綻しますけど。
/*
あと本題には関係ないのですが気になってるのが、
CPartsDataクラスのGet/Set関数の引数。
Get/Setの実装を見る限り、引数のCDataBoxクラス(構造体?)は
CPartsDataのデータメンバをpublicにしただけのクラス(構造体?)のような
気がします。
同じものを二度も書くのは、どうかと・・。
*/
みなさん色々ありがとうございます。
PATIOさんのアドバイスで昨夜やっていたのですが
reinterpret_cast<CAutoMationApp*>(AfxGetApp())->PD.GetData(引数)
だと上手くいったんですが、調べてみると
『reinterpret_castは単なる型変更であり、たとえ派生関係があったとしてもポインタ
のアドレス自体はキャスト前と変わりません。
その意味でreinterpret_castは非常に危険なキャストといえるでしょう。』
と書いてあったので、それならと思い
dynamic_cast<CAutoMationApp*>(AfxGetApp())->PD.GetData(引数)
『warning C4541: 'dynamic_cast' が /GR- を使用したポリモーフィック型 'class CWinApp'
で使用されています; 動作結果は保証されません。』との警告が
また調べてみますとプロジェクトの設定で
『ランタイムタイプ情報(RTTI)を有効にするにチェックしておうく・・・』
探したんですけどプロジェクトの設定にはないんです。
警告を無視して実行するとランタイムエラーが出て、デバックするとやは
り、dynamic_cast で『ハンドルされていない例外は AutoMation.exe(KERNEL32.DLL)
にあります:0xE06D7363:Microsoft C++ Exception』がでてしまいました。
そこで行き詰ってしまい、また質問します
Visual C++ 6.0 を使っています。
>>Get/Setの実装を見る限り、引数のCDataBoxクラス(構造体?)は
>>CPartsDataのデータメンバをpublicにしただけのクラス(構造体?)のような
>>気がします。
>>同じものを二度も書くのは、どうかと・・。
reshiaさんの指摘どおりなんですが、いつもデータを運ぶ空箱を作ってやっています。
他に何か良い方法があれば教えて下さい。
よろしくお願い致します。
キャストに関しては最近似たようなスレがあったので参考にしてみてください。
http://forums.belution.com/ja/vc/000/362/33s.shtml
最初のうちは使い分けるのが難しいので、
とりあえずCスタイルのキャストでも良いでしょう。
((CAutoMationApp*)AfxGetApp())->PD.GetData(引数)
まあ、ダウンキャストを使わざる得ないという時点で既に歪が出ているわけで
仕方ないのですけれどね。VC6ならプロジェクトの設定で開くC/C++タブを開き、
カテゴリのコンボボックスをC++言語にするとチェックボックスがありますよ。
プロジェクトの設定ウインドウに関しては全てのタブで全てのカテゴリの内容を
一度は確認しておくと良いです。あとであの辺にあったかもと気がつければ、
ベストなんですけどね。
reinterpret_castに関しては取得するポインタの実体がそれである事を
確実に保障できるのであれば、使用しても大丈夫です。
Cスタイルのキャストも同じ事をしてます。
なのでCの時はとんでもないキャストをしてとんでもない結果になることも多かった。
システム内でそのデータを取り扱う場合に必ず使うクラスを作成して
そのデータを扱うクラス内でもそのクラスを使うようにすれば、
空のクラスは要らないと思います。
この場合ならCPartsDataでデータの受け渡しもしてしまえば済むのでは?
引き渡し用に空の入れ物を別に用意する必要性の方が良くわからないと思いますけれど。
みなさん色々助けていただきありがとうございました。
今回教わった事を身に着けてレベルアップしていきます。
また質問する事が多々あると思いますが、その時もよろしくお願い致します。