2017-12-13 15 views
0

私はヒープ上に作成されたオブジェクトへのポインタを保持し、ハウスキーピングを担当するObjectクラスとObjectManagerクラスを持っています。すなわち、(例えば、オブジェクトが値によって関数に渡されたときなどのように、一時オブジェクトへのポインタを持ちたくない)。私は、ObjectManagerクラスの項目についていくつかの処理を行い、後でメモリを解放したいと思います。ヒープ上にのみ作成されたクラスのオブジェクトを管理および処理する方法は?

次のファイルをご検討ください:

"Object.h" ファイル

#pragma once 
#include<algorithm> 
#include "ObjectManager.h" 

class ObjectManager; 
class Object{ 
private: 
int value; 
static bool heap_flag; 

public: 

    Object() { 
     if (heap_flag) { 
      heap_flag = false; 
      ObjectManager::vo.push_back(this); 
      } 
     } 

    ~Object() {} 

    void* operator new (size_t sz){ 
     heap_flag = true; 
     return malloc(sz); 
    } 

    void setValue(int v) { value = v; } 

}; 

と "ObjectManager.h" クライアントコードで、最終的

#pragma once 
#include "Object.h" 
#include <vector> 

using namespace std; 

class Object; 
class ObjectManager{ 

private: 
    ObjectManager() {} 

public: 

static vector <Object*> vo; // vector that holds pointers to all objects created on heap 

static void releaseObjects() { 

    size_t index = 0; 
     for (auto o : vo){ 
      // iterate through the vector and delete the object create on heap 

      delete o; 
      vo[index] = NULL; 
      index++; 
     } 


    } 


}; 

#include <iostream> 
#include "Object.h" 
#include "ObjectManager.h" 

using namespace std; 

bool Object::heap_flag = false; 
vector<Object*> ObjectManager::vo; 

void process_Heap_objects (vector<Object*>) { 

// ... code to iterate through the elements of a vector and do some process 


} 

int main() { 

Object o; // created on stack 
Object* po = new Object(); // created on heap 

ObjectManager::vo[0]->setValue(100); 

process_Heap_Objects(ObjectManager::vo); 

ObjectManager::releaseObjects(); 

return 0; 
} 

whこのファイルをコンパイルすると、VS2013で次の警告が表示されます。 - > "警告C4150:不完全な型 'Object'へのポインタの削除。呼び出されていないデストラクタ 1> Objectmanager.h:。

の1-警告が何を意味する:

コードは罰金コンパイルしてかの期待どおりに動作

二つの質問「オブジェクト」」の宣言を参照してください?

2 - これはあなたの考えは何ですか?これを達成するためのより良い方法はありますか?良いデザインです?

+0

あなたはObject' 'は' virtual'デストラクタを持つようにしたい:使用することをお勧めしますほとんどのスタイルガイドには警備員が含まれていることをせず、あなたが 'へのポインタをdelete'ing未定義の動作を取得します派生型のオブジェクト。また、 'operator new()'を定義するときに、一致する 'operator delete()'を指定する必要があることに注意してください。 –

+0

良い点、私はこのクラスから派生するつもりはありません。 – Arash

+2

コンパイラにはObjectの前方宣言のみがあり、デストラクタがあるかどうかはわかりません。 releaseObjects()の前に定義する必要があります。 –

答えて

0

フォワード宣言されたクラスでデストラクタを呼び出すことはできません。

デストラクタコールは、デストラクタの宣言が見えるコンパイルユニットに置く必要があります(たとえば、#Object.hをインクルードする場所)。

また、文体のヒント:

  • パスで値によって:
    • オブジェクトはconstの場合は、REFによってfoo (const Object& bar) {}
    • を渡し、法により変異またはコピーするつもりされていない場合オブジェクトは変更されますが、メソッドによってコピーされず、参照渡しされますfoo (Object& bar) {}
    • オブジェクトがメソッドによってコピーされる場合は、値渡し
    • メソッドは、オブジェクトの所有権を取る場合、ポインタ渡し
  • プラグマは一度正式に標準の一部ではなく、めったに現世代のコンパイラでコンパイル高速化を提供しています。

    #ifndef SOME_NAME 
    #define SOME_NAME 
    ... body ... 
    #endif 
    
0

あなたの問題はあなたがObjectとの両方を定義して実装しているあります210をヘッダファイルに追加します。これは、各ヘッダーファイルが他のヘッダーファイルを含むため、循環依存関係を作成します。

より良い方法は、cppファイル内のメソッドのヘッダと本体にクラス定義を入れることだけです。

警告は、オブジェクトが定義されていないために表示されます。 #pragma onceがあるため、表示されるべきエラー(循環依存の影響)は表示されません。これにより、ObjectManagerがObjectクラスの定義方法を見ることができなくなります。

関連する問題