c++ - 如何正确使用具有抽象指针类型的模板类
问题描述
我创建了一个带有模板 Node 类的 List 来保存不同的数据类型,例如 Node<int>,但也包含更复杂的类型,例如 Node<BaseEvent*>。
我还有一个事件容器类来保存不同的事件对象,所以它有一个成员参数
List<BaseEvent*> events;
其中 BaseEvent 是具有非抽象派生类的抽象类。
在事件容器中,我有一个名为“add”(见下文)的方法,它向该事件添加一个新事件。
BaseEvent* eventClone = event.clone();
克隆返回一个指向新派生对象的指针,例如:
new OpenEvent(*this);
一旦它调用列表的插入方法,它就会实例化一个新节点(见下文),并在节点构造函数中分配值,如下所示:
value(new T(new_value))
所以基本上它分配了一个指针内存(T=BaseEvent*)。
我想我可能会丢失 eventClone 指针并且有内存泄漏。问题是,当我调试它时,我看到:(T* value;
又名BaseEvent** value
)和BaseEvent* eventClone
内存中的地址相同。
我不确定当我delete value
在 Node 的析构函数中这样做时,它是否只会释放指向 BaseEvent* 的指针分配或它所拥有的数据。
欢迎任何见解!
相关代码片段
节点<T>
template <class T>
class Node
{
public:
Node(const T& new_value, Node* new_next = NULL, Node* new_prev = NULL);
~Node();
const T& getValue() const;
Node<T>* getNext() const;
Node<T>* getPrev() const;
void setNext(Node* node);
void setPrev(Node* node);
private:
T* value;
Node* next;
Node* prev;
};
template <class T>
Node<T>::Node(const T& new_value, Node* new_next, Node* new_prev) :
value(new T(new_value))
{
next = new_next;
prev = new_prev;
}
template <class T>
Node<T>::~Node()
{
delete value;
}
...
使用 Node<T> 的链表
template <class T>
class List
{
public:
List();
~List();
int getSize() const;
Node<T>* getFirst() const;
Node<T>* getNext(Node<T>& node) const;
Node<T>* getPrev(Node<T>& node) const;
void insertStart(const T& data);
void insertLast(const T& data);
void insertAfter(Node<T>& target, const T& data);
void insertBefore(Node<T>& target, const T& data);
void removeNode(Node<T>& node);
bool contains(const T data);
private:
Node<T>* head;
int size;
};
template <class T>
List<T>::List() : head(NULL), size(0)
{
}
template <class T>
List<T>::~List()
{
Node<T>* temp;
while (head)
{
temp = head;
head = head->getNext();
delete temp;
size--;
}
}
...
template <class T>
void List<T>::insertStart(const T& data) {
if (size == 0)
{
head = new Node<T>(data);
}
else
{
Node<T>* temp = new Node<T>(data, head);
head->setPrev(temp);
head = temp;
}
size++;
}
...
事件容器类:
class EventContainer
{
public:
EventContainer() :
events(List<BaseEvent*>()) {}
~EventContainer() {}
virtual void add(const BaseEvent&);
class EventIterator
{
public:
EventIterator() :
current(NULL) {}
EventIterator(Node<BaseEvent*>& node) :
current(&node) {}
EventIterator(Node<BaseEvent*>* node) :
current(node) {}
~EventIterator() {}
EventIterator& operator=(const EventIterator& nodeIterator) {
current = nodeIterator.current;
return *this;
}
EventIterator& operator++() {
current = current->getNext();
return *this;
}
BaseEvent& operator*() const {
return *(current->getValue());
}
friend bool operator==(const EventIterator& iterator1, const EventIterator& iterator2) {
return iterator1.current == iterator2.current;
}
bool operator!=(const EventIterator& iterator) const {
return !(*this == iterator);
}
private:
Node<BaseEvent*>* current;
};
virtual EventIterator begin() const;
virtual EventIterator end() const;
private:
List<BaseEvent*> events;
};
方法的实现add
:
void EventContainer::add(const BaseEvent& event) {
BaseEvent* eventClone = event.clone();
if (events.getSize() == 0)
{
events.insertStart(eventClone);
return;
}
Node<BaseEvent*>* current = events.getFirst();
while (current != NULL)
{
if (*eventClone < *(current->getValue()))
{
events.insertBefore(*current, eventClone);
return;
}
current = current->getNext();
}
events.insertLast(eventClone);
}
EventContainer::EventIterator EventContainer::begin() const {
return events.getFirst();
}
EventContainer::EventIterator EventContainer::end() const {
return NULL;
}
解决方案
推荐阅读
- python - 限制 selectinload SQLAlchemy 关系上的返回记录
- bash - 如何使用带有该符号代码的变量打印符号?
- ios - 运行此代码时如何以及为什么会出现信号 SIGABRT?
- javascript - 带有 IEF、“静态”变量和事件的画布
- spring-boot - 如何使用 QuerydslPredicateExecutor::findOne() 在 SQL 选择中发出“LIMIT 1”?
- python - elif 和 else 命令被完全忽略,无论我输入什么,即使是随机字母,我总是得到 if 的答案
- sinon - 如何在 TypeORM 中使用 sinon 存根链接函数
- vue.js - 如何在 natviescript-vue vuex 商店操作中使用 $navigateTo?
- c# - 单击按钮以表单形式发送后,我想要一个模态
- html - 如何使用 CSS 最好地替代聊天气泡定位?