アプリケーション全体で管理するデータクラス – プログラミング – Home

アプリケーション全体で管理するデータク...
 
通知
すべてクリア

[解決済] アプリケーション全体で管理するデータクラス


yellow
 yellow
(@yellow)
ゲスト
結合: 18年前
投稿: 14
Topic starter  

お世話になります。

■概要
VC++/MFCで、ダイアログベースのアプリケーションを作成しています。

アプリケーションはダイアログを複数持ち、ダイアログごとに扱うデータの種類が異な
ります。
([ダイアログ1]では社員一覧、[ダイアログ2]では部署一覧、のような感じです。)

このため、それぞれのダイアログで扱うデータ一式をひとつのクラスとして定義し、ク
ラス群をアプリケーションクラスで一元管理したいと考えています。
(アプリケーション起動時にデータクラスをすべてインスタンス化し、アプリケーショ
ン実行中はそのインスタンスを使い続け、アプリケーション終了時にメモリを開放?す
るようなイメージでいます。)

技術的には、このような設計は可能だと思っていますが、具体的な実装方法、コーディ
ング方法がわかりません。

質問したいのは、以下2点です。
1.「データクラス」のインスタンス化処理および変数の初期化処理は、
  アプリケーションクラス(CXXApp)のどこに記述すればよいのでしょうか。
  --------------------------------------------------------------------
  【現状】
  CXXAppのメンバ変数として
   public:
    CXXDlgData dlgdata; 
  のように宣言していますが、コンパイル時に以下のエラーが出ます。

  error C2146: 構文エラー : ';' が、識別子 'dlgdata' の前に必要です
  error C4430: 型指定子がありません - int と仮定しました。
          メモ: C++ は int を既定値としてサポートしていません
  --------------------------------------------------------------------

2.アプリケーションクラス(CXXApp)でインスタンス化処理した「データクラス」
  のデータや処理をダイアログのクラスから使いたい場合、どのような方法で
  アクセスすればよいのでしょうか。
  

C++のオブジェクト志向については、入門書レベルの書籍でひととおり学んだつもりでお
りますが、MFCのアーキテクチャの中でこのような自前の「データクラス」を使う方法が
わかるほどには理解できていない状態です。

■補足
アプリケーションは以下のようなダイアログ及びクラスで構成されています。

【ダイアログ(リソース)】
IDD_CXX_DIALOG:アプリケーション起動時に最初に表示するダイアログ。
IDD_CXX_DIALOG2:IDD_CXX_DIALOGからのボタンクリックにより起動するダイアログ。

【クラス一覧】
CXXApp:アプリケーションクラス

CXXDlg:IDD_CXX_DIALOGに関する処理を定義するクラス。
CXXDlg2:IDD_CXX_DIALOG2に関する処理を定義するクラス。

CXXDlgData:CXXDlgクラスにて扱うデータ一式を持つデータクラス。
CXXDloData2:CXXDlg2クラスにて扱うデータ一式を持つデータクラス。

非常に初歩的な質問となり恥ずかしいのですが、よろしくお願いいたします。


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

CXXDlgDataのヘッダを#includeしてないだけのことじゃないかと推測されます。


返信引用
yellow
 yellow
(@yellow)
ゲスト
結合: 18年前
投稿: 14
Topic starter  

> επιστημη様
アドバイスありがとうございます。
ヘッダのincludeを確認したところ、ご指摘のとおりでした。
クラスのインスタンス化を記述している行よりも後にincludeがあったことが原因でし
た。ケアレスミスの範疇ですね。大変失礼いたしました。

上記問題点のうち、ひとつ目は解決しました。ありがとうございます。

以下の問題については、依然として解決しないままになっております。

2.アプリケーションクラス(CXXApp)でインスタンス化処理した「データクラス」
  のデータや処理をダイアログのクラスから使いたい場合、どのような方法で
  アクセスすればよいのでしょうか。

  --------------------------------------------------------------------
  【現状】
  ・CXXDlgクラス内にて、CXXDlgDataクラスのデータ(例:CString str)を
   取得したい。
  ・CXXDlgDataクラスは、アプリケーションクラス(CXXApp)のメンバ変数として
   インスタンス化している。
  --------------------------------------------------------------------
  ■CXXDlgDataクラスのヘッダ
#pragma once
class CXXDlgData : public CObject
{
public:
CXXDlgData(); // コンストラクタ
virtual ~CXXDlgData(); // デストラクタ
private:
CString str; // メンバ変数
public:
CString Getstr(){
return str; // データ取得用アクセス関数
}
}
  ■CXXDlgDataクラスの実装
#include stdafx.h
#include CXXApp.h
#include CXXDlgData.h

// コンストラクタ
CXXDlgData::CXXDlgData()
{
str=あああ;
}
// デストラクタ
CXXDlgData::~CXXDlgData()
{
}
  --------------------------------------------------------------------

  この状態で、ダイアログに関する処理を定義しているクラス「CXXDlg」内で
  CXXDlgDataクラスのインスタンス「dlgdata」に属するメンバ変数「str」を
  取得するには、どうすればよいのでしょうか?
  以下のように記述してみましたが、エラーとなります。

  error C2228: '.str' の左側はクラス、構造体、共用体でなければなりません

  --------------------------------------------------------------------
  ■CXXDlgクラス内での記述(エラーとなる)
  AfxMessageBox(CXXApp::dlgdata.str);
  --------------------------------------------------------------------

すみませんが、よろしくお願いいたします。


返信引用
PSB
 PSB
(@PSB)
ゲスト
結合: 20年前
投稿: 7
 

直接参照するのではなく、dlgdataをDoModal()でポインタで渡すなり、メンバ関数で
セットしてやるなりするべきと思われます。

#AfxGetApp()->dlgdata.str
#という反則技もありますけど・・・


返信引用
yellow
 yellow
(@yellow)
ゲスト
結合: 18年前
投稿: 14
Topic starter  

> PSB様
ご助言ありがとうございます。

「直接参照するのではなく」というご意見からヒントを得て、いろいろと試してみまし
た。
現在のところ、以下の方法でとりあえず解決の兆しです。
(アプリケーションクラス「CXXApp」でのデータクラス「dlgdata」のインスタンス
生成方法を変更し、externとしました。)

しかしながら、アプリケーションのつくりとしてOKなのか?
ナンセンスな事をしているのではないか?
という疑問が残ります。
また、現在作っているアプリケーションは、ダイアログが全部で50近くあり、
データクラスの数も同様で50近くとなる見込みです。
この方法で、パフォーマンスはどうなのか?等がちょっと心配です。

従いまして、まだ「解決」ステータスにはせずにおかせてください。
もう少し良い方法はないか、自分でも調べて見ます。

また、どなたか下記方法が変ではないかどうかご判断していただけますと大変有難いで
す。

  --------------------------------------------------------------------
  【現状】
  とりあえず以下の方法で動作しています。
  --------------------------------------------------------------------
  ■CXXAppクラスのヘッダ
   クラスのインスタンス生成の方法を変更。
   クラスの定義外に以下の記述をしました。
   extern CXXDlgData dlgdata;
  ■CXXAppクラスの実装
   以下の一文を追加しました。
   CXXDlgData dlgdata;
  --------------------------------------------------------------------
  ■CXXDlgDataクラスの実装
   以下のように修正しました。
  (コンストラクタによる値の初期化方法を変更。これはあまり関係ないかも)
#include stdafx.h
#include CXXApp.h
#include CXXDlgData.h

// コンストラクタ
CXXDlgData::CXXDlgData()
:str(あああ)
{
}
// デストラクタ
CXXDlgData::~CXXDlgData()
{
}
  --------------------------------------------------------------------
  ■CXXDlgクラス内での記述(エラーにはならず、値の取得可能!)
  AfxMessageBox(dlgdata.Getstr());
  --------------------------------------------------------------------


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 22年前
投稿: 1301
 

XXXDlg と XXXDlgData とが密接に関係しているなら、
XXXDlgDataをXXXDlgに渡してダイアログに書き換えてもらうことにすれば、
利用者はXXXDlgとのインタフェースを意識せんでええようになりますな。

XXXDlg : public CDialog {
XXXDlgData* data;
// - OnInitDialogあたりで*dataに基づいて
// コントロールを変更する
// - DialogのOKが押されたら、コントロールの状態に基づいて
// *dataを書き換える
public:
XXXDlg(XXXDlgData* target) : data(target), ...
};

とかやっとけば利用者側では:

XXXDlg dlg(AfxGetApp()->XXXdata);
dlg.DoModal();


返信引用
yellow
 yellow
(@yellow)
ゲスト
結合: 18年前
投稿: 14
Topic starter  

> επιστημη様

なるほど!
そういう方法がありますね。
データとダイアログを分離する目的で、ダイアログとデータクラスを一対一対応で作成
しているので、こちらの方法も検討してみます。

とりあえず、目的とする機能は実現できましたので、「解決」とさせていただきます。
皆様ありがとうございました。


返信引用
yellow
 yellow
(@yellow)
ゲスト
結合: 18年前
投稿: 14
Topic starter  

ステータスを「解決」とするのを忘れていました。
大変失礼いたしました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました