如何删除析构函数中的空指针?
Posted
技术标签:
【中文标题】如何删除析构函数中的空指针?【英文标题】:How to delete the void pointer in destructor? 【发布时间】:2017-02-09 11:14:43 【问题描述】:我有这样的课:
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
。
我怎样才能实现它?
【问题讨论】:
你能让item
指向一个基类,然后所有的实际项目都是从那个基类派生的吗?
我知道哪个事件包含哪个类型。那么为什么 item 不是事件本身的一部分呢?
我有很多事件,其中一半不包含任何项目。所以如果我将项目保留为事件的一部分(即枚举),我必须创建很多类。我认为 Martin Boner 解决方案很好。
所以你根据IncomingNetworkEvent
设置项目?所以我猜可能有一个 if-else 或 switch 构造,它从许多项目中选择一种类型并设置它。
是的,当我从服务器获取项目时,我设置了 IncomingNetworkEvent 并推送到 m_incomingNetworkArray。
【参考方案1】:
您可以创建一个ItemBase
类,从中创建所有项目。这个类将有一个虚拟析构函数。
现在不要将您的项目传递为void *
,而是将其向下转换为ItemBase *
,只要类型完整,您就可以delete
。
【讨论】:
【参考方案2】:你可以这样做:
class IncomingNetworkEvent final
private:
// ...
std::unique_ptr<void, void(*)(void*)> itemnullptr, [](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,你可以通过模板函数或者静态成员模板函数来达到同样的效果。
【讨论】:
以前我不能特别理解你的代码 std::unique_ptr您可以有一个非模板基类和一个模板派生类。然后事件向量保存指向基类的指针。
我还建议您在整个过程中使用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;
【讨论】:
以上是关于如何删除析构函数中的空指针?的主要内容,如果未能解决你的问题,请参考以下文章