• ベストアンサー

VisualC++ドキュメント/ビューアキテクチャについて

ものの本には『データはドキュメントクラスで管理し、ビュークラスではそこからデータをもらってくる』とし、データをドキュメントクラスのメンバ変数で作ることを推奨しているのですが、 データをファイルから読み込み、ビュークラスで表示、加工するようなアプリケーションにおいて、 (a) データをドキュメントクラスのメンバ変数(public)で作る、 (b) データを外部変数で作りどこからでも参照変更できるようにする、 でどう違うのでしょうか。 c/c++初心者です。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • wr250zb
  • ベストアンサー率41% (7/17)
回答No.2

どうしても言語から入ってしまうと言語仕様として どちらも出来てしまうので迷いますよね。 違いというと。。。 そのメンバ変数なり外部変数をアプリケーション上で 参照出来る期間(変数実体の寿命?)を考えてみます。 (a)の場合まずドキュメントオブジェクトのインスタンスが存在する間。 (b)はアプリケーション起動~終了迄。 となります。 変数をpublicなり外部変数なりにした場合の弊害について はsssoheiさんがおっしゃっている通りです。 オブジェクトを使ってアプリケーションを実装する考え方 (オブジェクト指向ですね)を身につけてください。 そちら側から考えてみるとわかりやすいですよ。 所詮言語は実装を表現する手段にすぎないのですから。。。

saikoro
質問者

補足

ありがとうございます。変数の違いについては理解できた(つもり)と思います。 で、MFC AppWizardが生成したコードをさらっと眺めてみたのですが、CxxDocの宣言らしきものが見当たりません。CxxDocのオブジェクトはどこで作られ、いつ消えるのでしょうか。 CxxView::OnDraw(CDC* pDC)の中で、 CxxDoc* pDoc = GetDocument(); がありますが、ここですか? 的をはずれは質問のような気がしますが、初心者に免じ、よろしくお願い致します。

その他の回答 (4)

  • sssohei
  • ベストアンサー率33% (33/98)
回答No.5

> > 内蔵をみせながら歩くようなもの > みせるけどいじられることはない、ということですか? 説明が不適切でした^^;ごめんなさい。 publicな変数は外からいじることが出来るので、どちらの場合もいじれますね^^; なお、(すこし正確ではありませんが)関数(インターフェース)を通じてメンバ変数にアクセスする様にする事を「カプセル化」と言います。 「中身を気にしなくても良くなる」というのが効用です。 # 作者を信頼すれば、、ですが。 例えば、ラジカセを操作するのに、CDを入れて、再生ボタンを押す。という事だけ知っておけばいい。ですよね。このとき。「CDを入れる」、「再生ボタンを押す」と言うのがインターフェースを通じた処理な訳です。 「ラジカセ」は「クラス」 「CDを入れる、再生ボタンを押す」はメンバ関数に相当します。 メーカーを信頼すれば、ラジカセがどのように動作しているかを気にする必要はありません。 CDの状態によってレーザーの強さを調節したりするのはラジカセに任せてしまいます。 外から、人がいじれると、下手したら壊れてしまうかも知れません。 # 分かってる人(制作者)にとっては、いじれた方が良いのかも知れませんが、全体から見れば、いじれない方が良いわけです。 他の部分も同様です。 そのため、パッケージで包んで、さわれなくしてある。と言うわけです。 こうすれば、外部からの介入の可能性を絞れますので、内部に処理を書きやすくなる、と言うわけです。 説明がうまく出来ず、長文になってしまいました(本当に、ごめんなさい。 馴れると感覚的に良さが分かってくると思います。

saikoro
質問者

お礼

オブジェクト指向は概念的にはわかっているつもりなんですが、いざコードを書く段になると、どこからでも何でもいじりたくなってしまいます。 いろいろな例題でもっと慣れる必要があると思います。 親切な説明を頂き、感謝しております。

  • wr250zb
  • ベストアンサー率41% (7/17)
回答No.4

>CxxDoc* pDoc = GetDocument(); これはビューにと結びついているドキュメントオブジェクトのポインタを取得しています。 ドキュメント、ビューのオブジェクトインスタンスを生成 しているのはMFCの内部が行っています。 このあたりについてはここで書くにはたいへんなので、 MSDNヘルプの「ドキュメント、ビューアーキテクチャ」 のあたりを見てください。 またはCXXXDocのコンストラクタにブレークポイント 張って止まったら、「コールスタック(Alt+7キー)」 でどこから呼ばれているか見てみるのも良いかもしれません。

saikoro
質問者

お礼

MFCでプログラムを書くのは、私の場合、お釈迦様の手のひらでおサルさんが遊ぶようなものみたいですね。 もう少し勉強してみようと思います。 いろいろ丁寧に説明いただき、ありがとうございました。

  • sssohei
  • ベストアンサー率33% (33/98)
回答No.3

> publicメンバ変数と、外部変数(正式名称かどうかわかりませんが、関数の外で定義する変数) グローバル変数で良いと思います>呼び方 それはさておき、グローバル変数は使わない、というのが現在の主流です。>メリットよりもデメリットが大きいので どうしても使いたいというような場面が思い当たらないのですが、いかがでしょうか?^^; なるべく、作る人間が楽になるような方法をとっていかないと、なかなか大変だと思います。 C++はCの流れを踏んだ言語なので、残っている遺物的な(というと言い過ぎかも知れませんが)言語仕様も残っています。 ちょっと極端な例えですが、 「データをドキュメントクラスのメンバ変数(public)で作る」というのは、内蔵をみせながら歩くようなものです。 「データを外部変数で作りどこからでも参照変更できるようにする」というのは、目の前に誰もいなくても、いつの間にか財布の中身がかわってしまったり、体の中をいじられてしまったり、、を出来るようにするようなものです。

saikoro
質問者

補足

わかりやすい説明ありがとうございます。 > 内蔵をみせながら歩くようなもの みせるけどいじられることはない、ということですか?

  • sssohei
  • ベストアンサー率33% (33/98)
回答No.1

大抵、データをドキュメントクラスのprivateメンバ変数にしておいて、publicなメンバ関数で間接的に操作します。>カプセル化 はじめは面倒なように感じるかも知れませんが、悪質なバグが減ることが多く、非常に効率の上がることが多いです。 この様にすることで思わぬ書き換えを防ぐコードを入れたり、と色々管理がしやすくなります。 関連している物がまとまっている方がわかりやすいと思うのですが、いかがでしょうか? また、データはそれぞれのクラスに密接に結びつくので、必要な所に、必要なだけ利用出来るというわけです。 ドキュメント/ビューアキテクチャに限らず、C++全般に対して重要な考え方だと思います。

saikoro
質問者

補足

privateメンバ変数+publicメンバ関数が有効だということは何となく理解できました。 publicメンバ変数と、外部変数(正式名称かどうかわかりませんが、関数の外で定義する変数)はどのように使い分けるのでしょうか。

関連するQ&A

  • ドキュメントクラスの取得方法

    MFC の SDI でアプリケーション開発をしています。 当方 “Hello, world!” を学び始めて数ヶ月のビギナーです。 ドキュメント・ビュー構造では ビュークラスからは GetDocument() 関数を使って, ドキュメントクラスの public な領域を操作することができます。 ここで質問です。 自分の作った,独自のクラスから,ドキュメントクラスを取得する には,どうしたらいいのでしょうか? GetDocument() 関数はビュークラスにしか(?)備わっていないようで,困っています。 ドキュメントクラスの ID でも分かれば GetDlgItem() が使えるかもしれない(?)などと思ったのですが。 初心者につき,変な質問をしているかもしれませんが,ご教授いただけると幸いです。

  • ダイアログから、ドキュメントのメンバ変数に設定するには

    MFCで現在 View-Documentの存在を知った程度の知識でプログラムを書いています。 MDI?形式でドキュメントにstrというCString型のメンバ変数を持たせています。 ViewからはGetDocumentで簡単にアクセスできますが、自作したダイアログボックス(例えばAbortのようなもの)の中にエディトボックスがあり、ここに入力された内容をドキュメントのメンバ変数strに代入したいのですが、どうすればよいのか分からず困っています。 あと、SDIやダイアログ形式でも同じように自作したダイアログのエディトボックスに入力した内容を設定したいです。 VBのInputBoxのようなことをしようとしていると想像してください。

  • 複数のドキュメントテンプレートを作成してから....

    MFCプログラミングにおいてMDIアプリケーションを作っています このアプリケーションではbmpやjpegなど、複数の画像のビューワーの役割をさせようと思っています CMainAppの派生クラスC**AppのIintInstance関数内で CMultiDocTemplate* pDocTemplate; を削除し C**Appのパブリックメンバ変数として CMultiDocTemplate* m_ptTemplate1; //bmp用 CMultiDocTemplate* m_ptTemplate2; //jpeg用 として定義しなおし 最後に AddSocTemplate(m_ptTemplate1); AddSocTemplate(m_ptTemplate2); を行いました ここまではなんとか出来たのですが、この次の段階で困っています アプリケーションを立ち上げてから [開く]で画像ファイル(bmpかjpeg)を開いた場合、 その動作を順に見て見ると CWinApp::onFileNew関数内  m_pDocManager->OnFileNew(); ↓ CDocManager::OnFileNew関数内 CDocTemplate* pTemplate= (CDocTemplate*)m_templateList.GetHead(); となっていました これだとbmpを選んでもjpegを選んでも GetHead関数によって、ドキュメントテンプレートは m_ptTemplate2になってしまいます これを避けるためにはやはり、 [開く]からbmpを選んだ場合とjpegを選んだ場合とで メッセージを変えて、 bmpならOnFileBmpNew関数へ jpegならOnFileJpegNew関数へ飛ぶように C**Appで独自のメンバ関数を作るべきでしょうか? またどのようにしてm_pDocManagerのどの位置にm_ptTemplate1とm_pTemplate2が格納されているか特定することができるのでしょうか? ここまでの疑問はbmp、jpegについてドキュメントテンプレートを分けて、 そのテンプレートをリスト管理するドキュメントマネージャーは同じものを使っていましたが、 もしかして、bmp、jpegについてのドキュメントマネージャーも分ける必要があるのでしょうか? ご教授よろしくお願いします

  • ダイアログからビュークラスのメンバ変数へ代入するには?

    プログラミング初心者です. Visual C++.netを使っています. Viewクラスから,Domodal()にてあるダイアログを呼び出しました. ダイアログ上のあるボタンを押したら,Viewクラスのメンバ変数へ1を代入するという処理をしたいと考えています.  ラジオボタンやエディタコントロールであれば,DDXを利用すればよいと思うのですが,単なるボタンの場合はどうすれば,呼び出し元のViewクラスの値を操作(この場合,代入)出来るのでしょうか?

  • java ローカル変数の値について

    素人ですが、どうぞ宜しくお願いします。 ローカル変数について教えてください。 リストビューでクリックされたアイテムをonItemClickメソッド内の変数に格納されているのですが、 通常スコープ外ではこの値は参照できないですよね? このようなローカル変数をスコープ外で参照する方法はあるのでしょうか? たとえば別のクラスや、別のメソッド内など。 ローカル変数の値を、メンバ変数に送るようなことって可能ですか? リストビューで選択された値を使いまわしたいのですが、 そんな方法がありましたら、ぜひご教授いただけないでしょうか? 宜しくお願いいたします!

    • ベストアンサー
    • Java
  • C++のクラス設計について

    Webや書籍をあたってみたのですが、なかなか解決しないので こちらで相談させいただこうと思い立ちました。 C++で書かれたプログラムを解析しているのですが、 ドキュメントは外部仕様書のみであとはソースコードだけ、という状態です。 コメントもほとんど書かれていないコードについて、リバースエンジニアリングを する必要があり、手始めにクラス図を作成してみました。 すると、複数のクラスでメンバ変数が重複しているのです。 クラスAに、クラスB・C・Dの変数の一部が宣言されていて、 クラスAとクラスBの間で重複している変数はすべてどちらのクラスもprotectedのstatic、 クラスAとクラスC・Dの間で重複している変数はクラスAではprotectedのstatic、 C・Dではprivateです。 クラスBとC・Dは継承関係にありますが、メンバ変数の重複はありません。 クラスAと他クラスは継承関係がなく、メンバ変数が多数重複しています。 クラスAの変数は20個ほどありますが、9割以上がB・C・Dで宣言されている変数と 重複している状態で、かつstaticのprotectedです。 Cはわかるのですが、C++はほとんど書いたことがありません。 アンチパターンなどもあたってみたのですが、上記のような設計についての記述は 見つけられませんでした。こういったクラス間での変数重複は「あり」なのでしょうか? これで情報が足りているかわかりませんが、何卒よろしくお願い致します。

  • クラスの外で宣言した変数について

    初心者的な質問ですみません。 クラスの外で宣言した変数をそのままクラス内で使うことはできないのでしょうか? publicのメンバーにポインタの変数を作ってそこにアドレス指定するか、setするメソッドを作るしかないのでしょうか? もしクラスの外で宣言した変数をそのままクラス内で使えないのは、スコープ的にどういう理由で使えないのか教えて下さい。 クラス内クラスだと子クラスは親クラスの変数を参照できますが、それとは違うのでしょうか? どうぞよろしくお願い致します。

  • VisualC#でデータの読み込み

    VisualC#の超初心者でプログラミングも初めてです。 文字や数値(整数や小数点あり)の大量データ(テキストファイル)から最大値や最小値等を求めるプログラムを作りたいのですが、まずデータの読み込みがよくわかりません。 Cの本やVisualC#の本を買って読んでいますが、いまひとつ理解できません。 また、CとC#の違いもよくわかりません。 よろしくお願いします。

  • 参照型のオフセット取得

    C++でリフレクションを実装するため、全メンバー変数のオフセット をoffsetofで取得し、メンバ変数名とオフセットをstd::mapに登録 しようとしています。 ここで質問なのですが、参照型に対してoffsetofを取得しようとすると アクセス違反で落ちてしまいます。原因を調べてみると、クラスの オブジェクトがobj、メンバ変数が参照型refだとすると、&obj.refは ref変数のアドレスを返すのでは無く、refが指している変数のアドレス を返してくるのが原因でした。 長くなりましたが、ref変数のアドレスを取得する方法、またはオフセット を取得する方法は無いのでしょうか?これが出来ないと、参照型については未サポートにするしか無くなってしまいます><

  • VisualC++の新規作成について。

    ちょっと古いですが、Windows98で「Visual C++ 6.0」を使用しています。C言語の解説本を見てを勉強しようとしている初心者です。 新規作成するときに[ファイル][新規作成][プロジェクト][Win32 Console Application]と選択して進み、プロジェクト名を入力して、[OK]を押すと [作成するコンソールアプリケーションの種類を選択してください] と表示され、 [空のプロジェクト] [単純アプリケーション] ["Hello,World!"アプリケーション] [MFCをサポートするアプリケーション] の四つの中から選ぶようになります。 作成する、プログラムは初心者向けの解説本に載っているようなまだ短めのプログラムなのですが、どれを選択すればよろしいのでしょうか? ためしに # include <stdio.h> int main(void) { printf("%d", 15 + 37); return(0); } とのプログラムを入力してコンパイルしてみましたが、 コンパイル中... prg.cpp c:\prg\prg.cpp(4) : fatal error C1083: プリコンパイル済ヘッダー ファイルがオープンできません。'Debug/prg.pch': No such file or directory cl.exe の実行エラー prg.obj - エラー 1、警告 0 と表示されてしまいます。 このまま、ビルドしようとしても 「ソース ファイル"C:\prg\prg.c"と"C:\prg\prg.cpp"はともに出力ファイル"C:\prg\Debug\prg.obj"を作成するために設定されています。プロジェクトをビルドできません」 と表示されるのです。 プログラムのプロジェクト名は「prg」で、ファイル名は「prg.c」です。 どなたか解決策をよろしくお願いいたいます。