如何删除析构函数中的void指针?

时间:2017-02-09 11:14:44

标签: c++ templates

我有一个这样的课程:

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的项目。所以要删除它我必须回到正确的类型 一个解决方案是在析构函数中根据事件对项目进行类型化(我知道哪个事件包含哪种类型)。但它会在析构函数中创建大量的switch case。

所以我想要一个像这样的解决方案:

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> m_incomingNetworkArray;

我必须声明为:

vector<IncomingNetworkEvent<someType>> m_incomingNetworkArray;

但这不能解决我的问题,因为m_incomingNetworkArray只会处理一种类型的IncomingNetworkEvent
我怎样才能实现它?

3 个答案:

答案 0 :(得分:3)

您可以创建一个ItemBase类,从中创建所有项目。这个类将有一个虚拟析构函数。

现在,不要将您的项目传递给void *,而是将其向下传播到ItemBase *,只要类型完整,您就可以delete

答案 1 :(得分:1)

您可以这样做:

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); }};
    }
};

我认为该对象拥有ptr的所有权,因为它也是要求删除它的人。
基本思想是你仍在删除原始类型(因此使用void*),但是在构造内部项时设置了正确的析构函数。

要使用它,您只需写下:

IncomingNetworkEvent ev;
ev.setItem(new int);

扣除将完成其余的工作。

如果由于某种原因无法使用std:: unique_ptr和lambdas,则可以通过模板函数或静态成员模板函数获得相同的结果。

答案 2 :(得分: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;