I have a class like this:
class IncomingNetworkEvent {
private:
IncomingNetworkEventForGame event;
void* item;
public:
IncomingNetworkEvent();
~IncomingNetworkEvent();
IncomingNetworkEventForGame getEvent();
void setEvent(IncomingNetworkEventForGame event);
void* getItem();
void setItem (void* item);
};
And a member variable in other class
vector<IncomingNetworkEvent> m_incomingNetworkArray;
When an event comes I create the IncomingNetworkEvent
and setItem
(item may be of different type based on event after type casting to void*
).After creating the IncomingNetworkEvent
I put it on the m_incomingNetworkArray
.
So there is a case when I want to clear the m_incomingNetworkArray.clear()
. It will call the destructor of IncomingNetworkEvent
but I have to delete item which is void
. So to delete it I have to typecast back to proper type.
One solution will be in destructor I typecase the item according to event (I know which event contains which type). But it will create lot of switch case in the destructor.
So I wanted a solution like this:
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);
};
So I can delete item in the destructor without typecasting. But the problem is I cannot declare incoming network array like:
vector<IncomingNetworkEvent> m_incomingNetworkArray;
I have to declare it as:
vector<IncomingNetworkEvent<someType>> m_incomingNetworkArray;
But this will not solve my problem as m_incomingNetworkArray
will can process only IncomingNetworkEvent
of one type.
How can I achieve it?
You can create an ItemBase
class from which all items are created. This class will have a virtual destructor.
Now instead of passing your Item as void *
, let it downcast to ItemBase *
and you would be able to delete
it as long as the type is complete.
You can do something like this:
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); }};
}
};
I assumed that the object takes the ownership of ptr
, for it is also the one demanded to delete it.
The basic idea is that you are still erasing the original type (thus using void*
), but you set a proper destructor when you construct the internal item.
To use it, you can simply write:
IncomingNetworkEvent ev;
ev.setItem(new int);
Deduction will do the rest.
If you can't use std:: unique_ptr
and lambdas for some reason, you can achieve the same result by means of a template function or static member template function.
You can have a non-template base and a template derived class. The events vector then holds pointers to the base class.
I also suggest that you use std::unique_ptr
to designate ownership throughout.
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;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.