- ベストアンサー
オブジェクト破棄の方法を教えてください
- c言語から入って、c++の勉強中なのですがオブジェクトの操作方法で破棄の仕方が解決できません。
- 入力から出力までの処理はできたが、(2)のダイアログでキャンセルした場合に1回目に読み込んだデータを破棄する方法が分からない。
- リストの破棄はできるが、リストに登録したオブジェクトの破棄方法がうまくいかない。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
>リストはRemoveAll()で削除できると思うのですが、リストだけの破棄ではオブジェクトは破棄されないんですよね? CListObj の動作ではオブジェクトの生成/破棄を行わないのでそのようになりますね。 > ※これを入力してて思ったんですが、もしリストにセットしたオブジェクトがさらに他のリストとか持ってたら、そのリストにセットされているオブジェクトも破棄し > なきゃいけないんですよね?(頭が混乱しそうです) はい。そのため、クラスにはデストラクタというものがあります。 class TestList :public CObList{ private: POSITION m_pos public: void ObjectSet(CObject*); ~TestList() // デストラクタ: クラス名と同じ名前で前に~(チルダ)がついている。 int FileRead(*fr); }; デストラクタについて。 このリストオブジェクトそのものが破棄された場合に各要素を破棄する必要がありますよね。 その処理は TestList::~TestList() { CObject *obj; while( ! IsEmpty() ) { obj = RemoveHead( ); delete obj; // ここでオブジェクト削除 }; } とすればCObjList blist; のblistが破棄されたときにリストの示すオブジェクトも破棄されます。 リストオブジェクトそのものは保持しておいて、オブジェクトの持っているリストをからにするには、RemoveAll()では実体が残りますので、RemoveHead()とdeleteの繰り返しが必要になります。 A)RemoveHeadをオーバーライド(この概念も重要です。調べてください)してしまうか、 B)別のメンバ関数を用意して、 obj = RemoveHead(); delete Obj; と処理する必要がありますね。 class TestObj :public CObject{ private: m_nData1;m_nData2; public: void SetData1( int ) {m_nData1=inddata;}; int GetData1(){return m_nData1;}; ~TestObj() // デストラクタ }; でも、もしnewして作る要素がなかにあるのであれば、 TestObj::~TestObj() { } というデストラクタの中にその要素を破棄(delete)する処理を仕込みます。 すると、 TestObj *aa; aa = new TestObj; delete aa; <-----ここでデストラクタTestObj::~TestObj()が呼ばれる。 とdeleteの処理のときにデストラクタが自動で呼ばれますので問題ないわけです。 もし、このときのTestObj に要素があり、その要素が前出のCTestListだったとします。 その場合、 TestObjのデストラクタTestObj::~TestObj() で、 delete m_ListObj // ここで、CTestList *m_ListObj とします。 としたときに、 TestList::~TestList() というデストラクタが起動されるので問題なく、リストが持っているオブジェクト群もdeleteされます。 C++では重要な処理なので覚えてくださいね。 この処理のために、new, free()関数は使われない、使ってはいけないのです。 (newではコンストラクタというものが起動される) メモリリークを防ぐためには、 "オブジェクトの中で new した要素がある場合には、必ずデストラクタで delete 処理すること。" (new で動的確保されていない要素であれば、気にしなくてもそのオブジェクトが破棄されるときにはかってにデストラクタが呼ばれるようになっています) class TestCObj { TestAObj m_testa; // 普通のメンバ。こちらは明示的にdeleteしなくてもTestCObjが破棄されるときに、TestAObjのデストラクタが呼ばれる。 TestBObj *m_testb; // こちらはポインタで後に、newで確保する。だから~TestCObj()でdeleteする処理が必要。 ~TestCObj() // デストラクタ } よろしいでしょうか?
その他の回答 (2)
リストのクラス型は何でしょうか。 MFCのCListやCObListなどでしたら、RemoveAll()というメソッドがあります。
補足
RemoveAll()は「オブジェクト自体はユーザーが削除する責任があります。」と説明がありましたがこれですべて破棄されるんでしょうか? ヘルプを見ていて思ったんですが、 while(GetNextでオブジェクトポインタをGet){ delete [オブジェクトポインタ]; } これでオブジェクトの破棄ができるのか試してみたいと思います。
もう少し質問内容に補足されないと、肝心の問題点、 >オブジェクトの破棄方法がうまくいきません。 がどううまくいかないのかがわからないですよ。 動的に確保したオブジェクトであれば、 new で生成、deleteで廃棄。 自動変数であればコンパイラにお任せ。(スコープ外で自動的に廃棄される) 静的に確保されているものであれば、廃棄は出来ない。 です。何をなさろうとしましたか?
補足
すみません、説明もうまく出来ていないですね。 テスト作成したのは、リスト内でオブジェクトポインタをnewして、そのオブジェクトポインタにデータをセットし、最終的にリストに登録しています。 この方法はnewで生成しているので動的なのだと思いますが、こんな感じです。 class TestObj :public CObject{ private: m_nData1;m_nData2; public: void SetData1( int ) {m_nData1=inddata;}; int GetData1(){return m_nData1;}; }; class TestList :public CObList{ private: POSITION m_pos public: void ObjectSet(CObject*); int FileRead(*fr); }; int FileRead(*fr){ while(fr->ReadString(lpRecord,size)){ ~データ取得(int n) TestObj* pObj = new TestObj(); pObj->SetData1(n); TestList->ObjectSet(pObj); } } かなり簡略化していますが、基本的にはこういう感じでデータの取得をしています。 リストはRemoveAll()で削除できると思うのですが、リストだけの破棄ではオブジェクトは破棄されないんですよね? これで分かるでしょうか? ※これを入力してて思ったんですが、もしリストにセットしたオブジェクトがさらに他のリストとか持ってたら、そのリストにセットされているオブジェクトも破棄しなきゃいけないんですよね?(頭が混乱しそうです)
お礼
とても丁寧に解説いただきありがとうございました。 デストラクタの重要さが良く分かりました。 後処理のことも考えて設計しなければいけないですね 本当にありがとうございました。