2017-02-09 4 views
2

は、私はこのようなクラスがあります。デストラクタでvoidポインタを削除するには?

class IncomingNetworkEvent { 
private: 
    IncomingNetworkEventForGame event; 
    void* item; 
public: 
    IncomingNetworkEvent(); 
    ~IncomingNetworkEvent(); 
    IncomingNetworkEventForGame getEvent(); 
    void setEvent(IncomingNetworkEventForGame event); 
    void* getItem(); 
    void setItem (void* item); 
}; 

そして、他のクラスのメンバ変数を

vector<IncomingNetworkEvent> m_incomingNetworkArray; 

イベントは、私がIncomingNetworkEventsetItem(アイテムは、イベントに基づいて異なるタイプのものであってもよい作成しています

タイプキャスト後に void*)。 IncomingNetworkEventを作成した後、 m_incomingNetworkArrayに貼り付けました。

したがって、m_incomingNetworkArray.clear()をクリアしたい場合があります。それはIncomingNetworkEventのデストラクタを呼び出しますが、私はvoidの項目を削除する必要があります。それを削除するには、適切な型に型変換し直す必要があります。
1つの解決策は、イベントに応じてアイテムをタイプチェクします(どのイベントにどのタイプが含まれているかわかります)。しかし、デストラクタには多くのスイッチケースが作成されます。

だから私はこのようなソリューションを求めていました:

template <class T> 
class IncomingNetworkEvent { 
private: 
    IncomingNetworkEventForGame event; 
    T* item; 
public: 
    IncomingNetworkEvent(); 
    ~IncomingNetworkEvent(); 
    IncomingNetworkEventForGame getEvent(); 
    void setEvent(IncomingNetworkEventForGame event); 
    T* getItem(); 
    void setItem (T* item); 
}; 

だから私は型キャストすることなく、デストラクタ内の項目を削除することができます。

vector<IncomingNetworkEvent<someType>> m_incomingNetworkArray; 

しかしm_incomingNetworkArrayだけIncomingNetworkEvent一種類のを処理することができますよう、これは私の問題を解決することはできません:私はとしてそれを宣言する必要が

vector<IncomingNetworkEvent> m_incomingNetworkArray; 

:しかし、問題は、私のような着信ネットワーク配列を宣言することはできませんです。
どうすれば実現できますか?

+1

'item'ポイントをベースクラスにすることができますし、実際のアイテムはすべてそのベースクラスから派生して作成できますか? –

+0

***どのイベントにどのタイプが含まれているかを知っています***。なぜアイテムはイベント自体に含まれていないのですか? – sameerkn

+0

私はたくさんのイベントがあり、その半分はアイテムを含んでいません。アイテムをイベント(enum)の一部にしておくと、たくさんのクラスを作成する必要があります。私はMartin Bonerソリューションが良いと思います。 – user1438832

答えて

3

すべての項目が作成されたItemBaseクラスを作成できます。このクラスには仮想デストラクタがあります。

あなたのアイテムをvoid *として渡す代わりに、ItemBase *にダウンキャストし、タイプが完了している限り、deleteにできるようになります。

1

あなたはこのような何か行うことができます:私はそれはまた、それを削除することが望ま1であるため、オブジェクトが、ptrの所有権を取得することを想定し

class IncomingNetworkEvent final { 
private: 
    // ... 

    std::unique_ptr<void, void(*)(void*)> item{nullptr, [](void*){}}; 

public: 
    // ... 

    void* getItem() { return item.get(); } 

    template<typename T> 
    void setItem (T* ptr) { 
     item = std::unique_ptr<void, void(*)(void*)>{ptr, [](void *ptr){ delete static_cast<T*>(ptr); }}; 
    } 
}; 

を。
基本的な考え方は、元のタイプを(つまりvoid*を使用して)消去していますが、内部アイテムを作成するときに適切なデストラクタを設定するということです。

それを使用するには、単に書くことができます。

IncomingNetworkEvent ev; 
ev.setItem(new int); 

控除が残りの作業を実行します。

何らかの理由でstd:: unique_ptrとlambdaを使用できない場合は、テンプレート関数または静的メンバーテンプレート関数を使用して同じ結果を得ることができます。

+0

以前はあなたのコードを特別に理解できません:: unique_ptr item {nullptr、[](void *){}}; 、第二引数が今私はそれを得た。タンックス – user1438832

+0

@ user1438832私は答えに詳細を追加しますか? – skypjack

+0

いいえ、私はあなたのコードを理解することによってあまりにも多くを学びます。 – user1438832

0

非テンプレートベースとテンプレート派生クラスを持つことができます。イベントベクタは、基本クラスへのポインタを保持します。

また、std::unique_ptrを使用して所有権を指定することをお勧めします。

class IncomingNetworkEventBase { 
private: 
    IncomingNetworkEventForGame event; 
public: 
    virtual ~IncomingNetworkEventBase() = default; 
    IncomingNetworkEventForGame getEvent(); 
    void setEvent(IncomingNetworkEventForGame event); 
}; 

template <class T> 
class IncomingNetworkEvent : public IncomingNetworkEventBase{ 
private: 
    std::unique_ptr<T> m_item; 
public: 
    T* getItem() { return m_item.get(); } 
    void setItem (std::unique_ptr<T> item) { m_item = std::move(item); } 
}; 

vector<std::unique_ptr<IncomingNetworkEventBase>> m_incomingNetworkArray; 
関連する問題