13.4 wxList和wxNode
wxList类是一个双向链表,可以用来存储任何类型的数据.wxWidgets需要你显式的定义一个针对某种数据类型的新的类来使用它,以便对存储于其中的数据提供足够的类型检查.wxList类还允许你指定一个索引类型以便进行基本的查找操作(如果你想使用基于结构的快速随机访问,请参考下一节的 wxHashMap类).
wxList使用了一个虚类wxNode.当你定义一个新的wxList派生类的时候,你同时定义了一个派生自wxNodeBase的类,以便对节点提供类型安全检查.节点类最重要的函数包括:GetNext,GetPrevious和GetData.它们的功能显而易见,分别为:获取下一个子项,获取前一个子项以及获取子项的数据.
唯一值得说明的是wxList的删除操作,默认情况下,从链表中移除一个节点并不会导致节点内部数据的释放.你需要调用 DeleteContents函数来改变这种默认的行为,设置数据随着节点一起释放.如果你想清除整个链表并且释放其中的数据,你应该先调用 DeleteContents,参数为True,然后再调用Clear函数.
我们用不着在这里把手册的内容重新粘贴一遍.我们将举一个简单的例子来演示怎样创建你自己的链表类型.注意WX_DECLARE_LIST宏通常应该位于头文件中,而WX_DEFINE_LIST宏通常应该位于源文件中.
// 我们将存储于链表的数据类型
class Customer
{
public:
int CustID;
wxString CustName;
};
// 通常应该位于头文件中
WX_DECLARE_LIST(Customer, CustomerList);
// 下面的定义应该位于源文件中,并且通常位于所有Customer声明之后
#include <wx/listimpl.cpp>
WX_DEFINE_LIST(CustomerList);
// 用于排序的比较函数
int listcompare(const Customer** arg1, const Customer** arg2)
{
return ((*arg1)->CustID < (*arg2)->CustID);
}
// 链表操作举例
void ListTest()
{
// 定义一个我们自定义链表的实例
CustomerList* MyList = new CustomerList();
bool IsEmpty = MyList->IsEmpty(); // will be true
// 创建一些自定义对象实例
Customer* CustA = new Customer;
CustA->CustID = 10;
CustA->CustName = wxT("Bob");
Customer* CustB = new Customer;
CustB->CustID = 20;
CustB->CustName = wxT("Sally");
Customer* CustC = new Customer;
CustC->CustID = 5;
CustC->CustName = wxT("Dmitri");
// 将其增加到链表中
MyList->Append(CustA);
MyList->Append(CustB);
// 实现随机插入
MyList->Insert((size_t)0, CustC);
int Count = MyList->GetCount(); // will be 3
// 如果找不到,返回wxNOT_FOUND
int index = MyList->IndexOf(CustB); // will be 2
// 自定义的节点里包含了我们自定义的类型
CustomerList::Node* node = MyList->GetFirst();
// 节点遍历
while (node)
{
Customer* Cust = node->GetData();
// 进行一些处理
node = node->GetNext();
}
// 返回特定位置的节点
node = MyList->Item(0);
// 按照排序函数排序
MyList->Sort(listcompare);
// 移除包含某个对象的节点
MyList->DeleteObject(CustA);
// 我们需要自己释放这个对象
delete CustA;
// 找到包含某个对象的节点
node = MyList->Find(CustB);
// 指示内部数据随节点的删除而删除
MyList->DeleteContents(true);
// 删除B的节点的时候,B也被释放了
MyList->DeleteNode(node);
// 现在调用Clear,所有的节点和其中数据都将被释放
MyList->Clear();
delete MyList;
}