#pragma twice

KAB-studio > プログラミング > #pragma twice > 047 Version 3.22 参照を作ろう!

#pragma twice 047 Version 3.22 参照を作ろう!

前のページへ 表紙・目次へ 次のページへ

 Version 3.22
参照を作ろう!

さて今回は?
えっと、この前〈答に数字を入れる〉ってのをしたから、今度はその数字
をレジストリのにするんだよね。でも……
そう、うまくいきません。ま、試してみて
ま、試してみたら偶然うまくいくかもしんないし
それはない
うー。えっと、前は CCalcApp::InitInstance() の中で

    CString cCompanyStr;
    cCompanyStr.LoadString( IDS_REG_COMPANY );
    CString cDialogStr;
    cDialogStr.LoadString( IDS_REG_DIALOG );
    CString cAnsStr;
    cAnsStr.LoadString( IDS_REG_ANS );

    SetRegistryKey( cCompanyStr );
    dlg.m_iAns = GetProfileInt( cDialogStr, cAnsStr, 0 );

って書いて、この前 CCalcDlg::OnInitDialog() で

    // TODO: 特別な初期化を行う時はこの場所に追加してください。
    dlg.m_iAns = 10000;

って書いて、こっちの方に移動すればいいんだから……
あ、切り取っちゃダメだよ、 cDialogStr とかはあとで使ってるんだから
 OK ボタン押したとこのことね
あと SetRegistryKey() は CCalcApp::InitInstance() で呼んだ方がいい
かな。これは〈アプリケーションの設定〉だから
ダイアログと関係ないってことね。じゃ、こんな感じ

    // TODO: 特別な初期化を行う時はこの場所に追加してください。
    CString cDialogStr;
    cDialogStr.LoadString( IDS_REG_DIALOG );
    CString cAnsStr;
    cAnsStr.LoadString( IDS_REG_ANS );

    m_iAns = GetProfileInt( cDialogStr, cAnsStr, 0 );

だねー。簡単簡単!
で?
はいはい。ビルドしてエラー……にならない。あれ?
良かったね、エラーにならなくて
……なんかあんね
じゃ、実行してみて
はーい……あれ、なんで【Ans】のとこが 0 なの? えっと、 100 入れ
て【OK】ボタン押して、もう一度実行……あれぇ、また 0 、なんでぇ?
ミスがふたつ。まず、  UpdateData( FALSE ) を付け加えて
え、なんで?
理由は次回。あともうひとつのミスは、 GetProfileInt() 。これ、さっ
きのと今のとで違う関数が呼ばれてるんだよ
??
 CCalcApp::InitInstance() で呼んだのは CWinApp::GetProfileInt() 、
CCalcDlg::OnInitDialog() で呼んだのは GetProfileInt() 、つまり API 
の関数
い、いつのまに……
なんでか分かる?
分かんない
……
あ、えっとねぇ……
 CWinApp::GetProfileInt() ってことは CWinApp のメンバ関数だから?
あ、確か今のプログラムって CCalcDlg::OnInitDialog() の中だから
そう、 GetProfileInt() が属してる CWinApp クラスと別ってこと
だから呼べなくって、代わりに API の方が呼ばれちゃったんだ
じゃあ、どうすれば CWinApp の方を呼べると思う?
んー、たとえば dlg.GetProfileInt() みたいに使えたりするんじゃな
い?
当たり。じゃ、 dlg に当たるものは?
……えーっと
 GetProfileInt() はどこで使ってたの?
 CCalcApp::InitInstance() の中
そこでなんで使えるの?
あ、えーっと、 CCalcApp が CWinApp から継承してるからなんだよね。
CCalcDlg の中で UpdateData() とかが使えるのと同じで
ってことは dlg に当たるのは?
んー、この前言ってたよね、 CCalcDlg::OnInitDialog() の中じゃ、
CCalcDlg じゃなくて、例えば dlg 変数の中、とかで考えた方が分かりやす
いって
うんうん
ってことは、 GetProfileInt() を呼んだとき、 CCalcApp は dlg に当た
る変数になってる!
そうそう
それが分かれば CCalcDlg::OnInitDialog() の中から GetProfileInt()
を呼ぶこともできるはず!!
そう!
……で?
で?
 dlg はさ、 CCalcApp::InitInstance() の中で CCalcDlg dlg; って感じ
に変数として作ったでしょ。でも CCalcApp の変数は?
前に一度見たんだけどねー
検索っ! ……あーっ、Ver 3.1 ( No.026 )で教えてもらったんだね
そ、 CCalcApp::InitInstance() のすぐ上に CCalcApp theApp; ってある
でしょ、これがそう
まず CCalcApp の変数ができて、そのあと CCalcApp::InitInstance() が
呼ばれて、その中で CCalcDlg の変数ができて、ダイアログが表示されて、
ってやったもんねー
思い出してきた?
なんとなく。んじゃ!

    m_iAns = theApp.GetProfileInt( cDialogStr, cAnsStr, 0 );

ビルドして実行! ほらエラーってなんでぇ??

error C2065: 'theApp' : 定義されていない識別子です。

なんでぇ〜!?
 theApp はどのファイルにある?
 Calc.cpp 
 CCalcDlg::OnInitDialog() は?
 CalcDlg.cpp 。もしかして、ファイルが違うから?
そうとも限らないでしょ。 CCalcApp::InitInstance() の中で CalcDlg 
を使ってるでしょ?
あ、そういえば
つまり〈他のファイルにあるのを使う方法がある〉ってこと
なるほど。で、その方法とは?
じゃ、まず CCalcApp theApp; のあとに

CCalcApp theApp;
// のあとに、

CCalcApp& GetTheApp()
{
    return theApp;
}
// と書き足してください。

はて? これは関数だよね……あれ?
Ver 2.10 ( No.021 )とか思い出してみて。普通の関数を作ったでしょ
あ、そういえば。メンバ関数じゃない、普通の関数
じゃ、思い出しながら見ていこうか。まず関数名は?
えっと、 GetTheApp() 。だからこれ呼べば、この関数使えるんだよね
じゃ、戻り値は?
…… CCalcApp& かな、でも最後の & って?
それが今回の注目点。この関数の中は?
えーっと、 return って〈戻り値〉っていうのを決めるんだよね。だから
GetTheApp() が theApp に置き換わる……あ、こうやると CCalcDlg からも
theApp が使えるようになるんだ!
まだ早いって。戻り値が CCalcApp& でしょ
そう、この & ってなに? theApp は CCalcApp の変数なんだから、 & 
なんていらないんじゃない?
じゃ、取ってビルドしてみれば
うー、エラーでたー

error C2558: class 'CCalcApp' : コピー コンストラクタが(略)。

これは〈 theApp の複製は作れませんよ〉って意味
複製?
そう、コピーね。 return theApp ってすると、 theApp そのものじゃな
くて、 theApp のコピー、つまり新しく作られた CCalcApp 型の変数が、
GetTheApp() の代わりとして置かれるわけ
えー?? なんで theApp そのものじゃないの〜、めんどくさー
というわけで、戻り値の型のあとに & を付けます!
ってことは、これを付けると
 theApp そのものが返るから、コピーは作られません!
なるほど、そのための & なわけね
この & の付いた型を〈参照〉っていいます。この例なら〈 CCalcApp の
参照〉って言い方をします
参照って〈これはテキスト24ページを参照してください〉とかのと同
じ?
同じ。参照使わなかったら、そのテキストをコピーして見てもらうってこ
とだね
それは無駄だから参照、か〜
でもこれだけじゃまだダメ
え、そなの?
 GetTheApp() は Calc.cpp にあるでしょ。だからまだ CCalcDlg からは
呼べないって、それじゃ意味ないじゃん
そこで、この関数の〈宣言〉を作りましょう
宣言って…… GetTheApp() がここにあるぞ、使え!! ってのだよね
そうそう。これをヘッダーファイル、つまり Calc.h に書きます
そういえばそんな話あったね
やってみる?
う”
んじゃここは僕の方で。 Calc.h の中に CCalcApp が入ってるでしょ
うん、 class CCalcApp ってのでしょ
この CCalcApp のあとにこれを追加してください

class CCalcApp : public CWinApp
{
    // 略。
};

//  この下の行を追加。
CCalcApp &GetTheApp();

あ、そっか、関数のをそのまんま書けば良かったんだね
ちなみに CCalcApp のあとじゃなきゃダメだから
なんで?
 GetTheApp() の戻り値が CCalcApp だから。これ使う前に、 CCalcApp 
がどういうのか分かんないとね
そういえばそんな話も……
で、 CalcDlg.cpp から Calc.h をインクルードしてるから
 CCalcDlg から GetTheApp() が使える!!
というわけで

    m_iAns = GetTheApp().GetProfileInt( cDialogStr, cAnsStr, 0 );

で、めでたく
??
あ、ちょっと難しいかな。 GetTheApp() は theApp に置き換わるんだか


    m_iAns = theApp.GetProfileInt( cDialogStr, cAnsStr, 0 );

と同じことってことだね
ホントはこうはできないけど、 GetTheApp() を使えばこれと同じことが
できるってことなんだ
そういうこと

/*
    Preview Next Story!
*/
って難しくないー?
でも、関数のとか、前にやったのばかりだけど
そう言われればそうだけど〜
難しいことも簡単な知識の積み重ね
大きいプログラムも小さなプログラムが組み合わさってできてる、ね
というわけで次回
< Version 3.23 オーバーライド >
につづく!!
今回だって、新しく教えたの参照くらいだよ
つまり、憶えなきゃいけないことまだまだたっぷりあるってことね……
憶えてくれるまで繰り返し言ってるつもりだけどね
はいはい
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。