66588


## 環境

Windows10 64bit  
VisualStudio2019

  

## 現象

MFCにて、ダイアログベースでプログラムを作成し、  
ダイアログを1つ追加し、ダイアログ間で値を受け渡そうとしています。

※2つのダイアログを下記で表現します。  
ベースのダイアログ：ダイアログA  
追加したダイアログ：ダイアログB

ダイアログAから、ダイアログBにint型の値を渡し  
ダイアログBの関数内ではポインタを受け取るようにしました。

すると、ダイアログBのOnInitDialogのときにはポインタの値が  
変化してしまい値を渡すことに失敗しました。

なぜかわからないので教えていただけないでしょうか。

  

## プログラム概要

【ダイアログA】  
エディットコントロールがあり、そこに数値を入力できる。  
DialogBを開くボタンがあり、そのボタンが押下されるとエディットの値をDialogBに渡したあとDoModalする。

【ダイアログB】  
ディットコントロールがあり、DialogBから受け取った値をそこに表示する。

  

## ソースコード

[code]

    /*DialogA.h*/
    
    public:
        afx_msg void OnBnClickedButton1();
    
    private:
        int m_no;
    
[/code]

[code]

    /*DialogA.cpp*/
    
    // DialogBを開くためのボタンを押下したときの処理
    void CDialogADlg::OnBnClickedButton1()
    {
        DialogB dlg;
        CString strNo;
        CWnd* Edit = GetDlgItem(IDC_EDITA);
    
        //エディットに表示されている文字列を取得
        Edit->GetWindowText(strNo);
    
        //文字列を数値型に変換
        m_no = _ttoi(strNo);
    
        //DialogBに数値を渡す
        dlg.setData(m_no);
    
        dlg.DoModal();
    }
    
[/code]

[code]

    /*DialogB.h*/
    
    public:
        void setData(int no);
    
    private:
        int* m_pNo;
    
[/code]

[code]

    /*DialogB.cpp*/
    
    void DialogB::setData(int no)
    {
        //受け取った数値型のポインタをメンバポインタ変数に格納
        m_pNo = &no;
    }
    
    BOOL DialogB::OnInitDialog()
    {
        CDialogEx::OnInitDialog();
    
        /* この時点で、DialogAから受け取ったポインタ変数の値（*m_pNo）が変わっている・・・なぜ？？ */
    
        CString strNo;
    
        CWnd* Edit = GetDlgItem(IDC_EDITB);
    
        strNo.Format(_T("%d"), *m_pNo);
    
        Edit->SetWindowText(strNo);
    
        return TRUE;
    }
    
[/code]

  

## やりたかったこと

ダイアログ間でデータをやりとりしたかった。  
ポインタでやりとりすることにより、DialogBで入力した値がDialogAの値に反映されるようにしたかった。


CC BY-SA 4.0
2020-05-14T02:03:29.723
66585
2020-05-14T03:47:34.017
38241
question
c++ mfc
ダイアログ間で、ポインタで数値のやり取りを行おうとすると値が変わってしまう


> ダイアログAから、ダイアログBにint型の値を渡し  
>  ダイアログBの関数内ではポインタを受け取るようにしました。

C++言語では値がコピーされます。つまり１行目の時点で、ダイアログB側は一時的な領域（スタック）にコピーしています。一時的な領域なため`DialogB::setData`関数を抜け出た段階で領域が開放され再利用されます。ですので２行目の段階でアドレスを取得しポインタとしても既に遅いです。

ダイアログAから、ダイアログBにポインタを渡す必要があります。

* * *

一般的なC++言語ではポインタではなく参照を使います。ただし、MFCは参照への対応が不十分なため参照を使用するとかえって混乱するため、MFCと併用される際には無理に参照を使用せず引き続きポインタを使用されることをお勧めします。


CC BY-SA 4.0
2020-05-14T03:24:20.053
66587
2020-05-14T03:24:20.053
4236
66585
answer

[code]

    void DialogB::setData(int no)// noはスタック上の整数
    
[/code]

がやりたいことと一致していないようです。  
この場合、変数「no」の中身は「DLG-Aのm_no」の「値のコピー」ですが、  
「no」のアドレスはスタック上に取られてしまい「DLG-Aのm_no」のアドレスとは異なります。以下の様に変更してみてはどうでしょう。

[code]

    // DLG-A
    CDialogADlg::OnBnClickedButton1()
    {
        :
      dlg.setData( &m_no); // アドレスを渡す
      dlg.DoModal();
    }
    
    // DLG-B
    void DialogB::setData(
       int *     ot_pNo) // アドレスを受け取る
    {
       m_pNo =  ot_pNo; // アドレスのコピーを取る
    }
    
[/code]

ただし、個人的には  
「DLGの寿命は一時的で短命なので、そのメンバのアドレス=ポインタを参照すべきではありません」  
と、思ってます。  
この場合、

[code]

    // DLG-A
    CDialogADlg::OnBnClickedButton1()
    {
        :
      dlg.setData( m_no);   // 初期値を渡す
      dlg.DoModal();        // 編集する
      m_no = dlg.getData(); // 編集した値を取得する
    }
    // DLG-B
    void DialogB::setData(
       int      ot_No) // 初期値値を受け取る
    {
       m_Value =  ot_No;
    }
    int  getData() const 
    {
       return m_Value; // 編集結果値を戻す
    }
    
[/code]

の様な仕組みの方が簡単かつ安全です。


CC BY-SA 4.0
2020-05-14T03:39:29.990
66588
2020-05-14T03:47:34.017
2020-05-14T03:47:34.017
3793
3793
66585
answer