CArrayについて

解決


虫眼鏡  2009-06-12 01:46:53  No: 70334

VS2003.netでMFCを使って趣味で勉強しています。
SDIで作成したプロジェクトにCTemplクラスを追加して
CTempl::CTempl()
: m_strName(_T("nagasawa"))
, m_strAddress(_T("tokyo"))
{
}

CTempl::CTempl(CString strName, CString strAddress)
{
  m_strName = strName;
  m_strAddress = strAddress;
}
としました。
CXXXDoc.h にCArrayのテンプレートを宣言、.h、.cppに関数を追加。
public:
  CArray<CTempl*, CTempl*&> m_caTempl;
----------------------------------------------------
void CXXX02Doc::myTest(CString strname, CString straddress)
{
  CTempl* pObj = new CTempl(strname, straddress);
  INT_PTR iObj = m_caTempl.Add(pObj);//カウントは上がるが、CXX0030:エラーです:式を評価できません
  int nNum = m_caTempl.GetSize();
  for(int nI=0; nI<nNum; nI++) {
    INT_PTR ip = (INT_PTR)nI;
    CTempl* pcaObj = m_caTempl.GetAt(ip);// ここでは落ちません。

    CString str0 = pcaObj->m_strName;// 実行時、ここで落ちる
  }
  return;
}

コンパイルが通るのですが、XXXViewのメニューから呼び出すと
ハンドルされていない例外が発生しました。
読み込み中にアクセス違反が発生しました。
pcaObjが
CXX0030:エラーです:式を評価できません

とエラーになります。
CArrayを使わずに配列なら問題なく処理されるのですが
CTempl* m_pTempl[100];

m_caTempl.Add(pObj);でカウントは上がるけれど何故駄目なのか
訳が分からなくなってしまいました。


επιστημη  URL  2009-06-12 06:46:07  No: 70335

↓再現できませんでした。なんの問題もありません。ちゃーんと動いてくれます。

// cl -EHsc -D_AFXDLL -MD foo.cpp

#include <afxwin.h>
#include <cstringt.h>
#include <afxtempl.h>
#include <iostream>

struct CTempl {
  CString m_strName;
  CString m_strAddress;
  CTempl() : m_strName(_T("nagasawa"))
                  , m_strAddress(_T("tokyo"))
  {}

  CTempl(CString strName, CString strAddress) {
    m_strName = strName;
    m_strAddress = strAddress;
  }
};

int main() {
  CArray<CTempl*, CTempl*> m_caTempl;
  CTempl* p;
  p = new CTempl(_T("Hello"),_T("world"));
  m_caTempl.Add(p);
  p = new CTempl(_T("Adam"),_T("Eve"));
  m_caTempl.Add(p);
  p = new CTempl(_T("Red"),_T("Blue"));
  m_caTempl.Add(p);
  int nNum = m_caTempl.GetSize();
  for(int nI=0; nI<nNum; nI++) {
    CTempl* pcaObj = m_caTempl.GetAt(nI);
    CString str0 = pcaObj->m_strName;
    std::cout << static_cast<const char*>(str0) << std::endl;
  }
}


虫眼鏡  2009-06-12 11:10:21  No: 70336

επιστημηさん、ありがとうございます。

初心者で独学なのでCArrayの使い方として変な事をしているのだろうと
思っていたので、使い方自体は問題ない事を教えて頂いた事は大きな収穫です。

ダイアログベースでもεπιστημηさんのコードのstructをXXXDlg.hに
mainの中のコードを.cppに記述してみたのですが、
CString str0 = pcaObj->m_strName;で同じエラーが発生します。

CArrayの使い方は問題ないという事なので、もう少し力を付けるまでの自分への課題とします。
VS2003をもっと理解できるようになれば解決できるのかもしれません。

独学なのでCArrayの使い方に問題があると1ヶ月近く試行錯誤していました。
επιστημηさんに見て頂いて本当に助かりました。
ありがとうございました。

一人でどうしようもない時はよろしくお願いしたします。


yoh2  2009-06-13 08:05:04  No: 70337

m_caTemplに対して、どこかでうっかりZeroMemory()や
memset()をしてしまっている、ということはありませんか?


虫眼鏡  2009-06-13 21:30:10  No: 70338

yoh2さん、ありがとうございます。

自分では記述はしていないのですが、VSが自動でやってくれる事をまだ理解できていないのでやっていないという確信がありません。
訳が分からなくなって落ち込んでいたのですがεπιστημηさんにコメントを頂いて元気が出てまた挑戦しています。

動作確認では基本的に新規でSDI(時々、ダイアログ)を選択して他はデフォルトで行っています。

現時点ではCArrayのAddすると引数無しのコンストラクタのインスタンスが追加されるように見えます。
そこでInsertAtを使ってみました。

今回はCArray用のクラスをDoc.hに
class CTempl{
public:
    CTempl(LPCTSTR strName, LPCTSTR strAddress)
        :m_strName(strName), m_strAddress(strAddress)
  {
  }

  CTempl()
    :m_strName(_T("aragaki")),m_strAddress(_T("okinawa"))
  {
    
  }

    CString m_strName;
    CString m_strAddress;
};

public:
  CArray<CTempl, CTempl&> m_TData;

View.cppに(メニューのイベントから呼び出し)
void CTemplate06View::OnTemplateTemplate1()
{
  // TODO : ここにコマンド ハンドラ コードを追加します。
  CTemplate06Doc *pDoc = GetDocument(); 
  CString strText1 = _T("nagasawa");
  CString strText2 = _T("tokyo");
  CTempl data1(strText1, strText2);
  //pDoc->m_TData.Add(data1);
  pDoc->m_TData.InsertAt(0, data1);
  CString str0 = pDoc->m_TData[0].m_strName;
  AfxMessageBox(str0);

  strText1 = _T("igarashi");
  strText2 = _T("oosaka");
  CTempl data2(strText1, strText2);
  //pDoc->m_TData.Add(data2);
  pDoc->m_TData.InsertAt(1, data2);
  str0 = pDoc->m_TData[1].m_strName;
  AfxMessageBox(str0);
}

これで[nagasawa],[igarashi]が返るようになりました。
ここでAddの方にすると2回[aragaki]が返ってきます。

Addする場合は宣言の仕方が違うのか、なぜ、このような動作になるのかまだ分かりません。


虫眼鏡  2009-06-14 05:22:35  No: 70339

初心者なのでコードだけを疑っていましたが、επιστημηさんも問題がないと仰られているので、VSが問題なのではないかと思い始めました。

一旦削除して再インストールをしてみる事にします。
終わった後でご報告致します。


Blue  2009-06-14 07:57:50  No: 70340

本当にnewしたものを入れましたか?
どこかでdeleteしているとかありえませんよね?

というか、デバッグして、メンバ変数の中身を確認してみてはどうでしょうか?


虫眼鏡  2009-06-14 09:03:35  No: 70341

動きました。
Addで処理できました。

Blueさん、ありがとうございます。
デフォルトで作ったスケルトンに2009/06/13(土) 12:30:10のコードを
入れただけでした。

本当に長い時間これと格闘してしまいました。
επιστημηさんにコードに問題がないと言って頂けなければ
今でもきっとコードと格闘していたと思います。

気持ちよく次の課題に進めます。
本当にありがとうございました。


επιστημη  URL  2009-06-14 11:00:39  No: 70342

なんつーか、モヤっとしたものが拭えないわけですが ^^;
で、結局何が原因だったのでしょか。


虫眼鏡  2009-06-14 18:45:55  No: 70343

επιστημηさん、すみません。

私に力があればこれだという原因を掴めたと思いますが、
επιστημηさんに動くと確認して頂いたコードも
一人でやっている時は絶対何か間違えていると思っていたレベルなので
pDoc->m_TData.InsertAt(0, data1);
で上手くいって
//pDoc->m_TData.Add(data1);
で引数無しのコンストラクタの値が返ってくるとなった時に
一度再インストールしてみることを選択してしまいました。

επιστημηさんには、この呪縛から解放して頂いたのに
逆にモヤッとさせてしまって本当に申し訳ございませんでした。

少しずつでも深い部分まで追求できるように頑張りたいと
思っていますのでよろしくお願い致します。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加