我有一个这样的课程:
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;
当一个事件发生时,我创建了IncomingNetworkEvent
和setItem
(项目可能是基于类型转换为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
。
我怎样才能实现它?
答案 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;