我写一个工人阶级的模板,这也可能只是一个愚蠢的问题,但如果我有一个模板结构(链表)到可能持有对象的指针,然后我怎么知道他们正在被删除,还是他们在哪里指针?确定模板类型是动态
例如:LinkedList的将在第2种方式使用在此程序
一个指针指向类的东西的物体被放置在节点内的链表
枚举被放置在节点内的内部内一个linkedList
我知道节点正在被删除,但我怎么知道节点中的东西是一个指针,以便它可以被删除,而不仅仅是一个空引用对象?
我写一个工人阶级的模板,这也可能只是一个愚蠢的问题,但如果我有一个模板结构(链表)到可能持有对象的指针,然后我怎么知道他们正在被删除,还是他们在哪里指针?确定模板类型是动态
例如:LinkedList的将在第2种方式使用在此程序
一个指针指向类的东西的物体被放置在节点内的链表
枚举被放置在节点内的内部内一个linkedList
我知道节点正在被删除,但我怎么知道节点中的东西是一个指针,以便它可以被删除,而不仅仅是一个空引用对象?
您可以专注基于对象的类型的节点,并为指针专业化,创建节点型,妥善分配,并删除节点管理的指针析构函数。
例如:
//general node type for non-pointer types
template<typename T>
struct linked_list_node
{
T data;
linked_list_node<T>* next;
linked_list_node(const T& d): data(d), next(NULL) {}
~linked_list_node() {}
};
//specialized version for pointer types
template<typename T>
struct linked_list_node<T*>
{
typedef void (*deleter)(T*);
T* data;
linked_list_node<T>* next;
deleter d_func; //custom function for reclaiming pointer-type
linked_list_node(const T& d): data(new T(d)), next(NULL), d_func(NULL) {}
linked_list_node(const T& d, deleter func): data(new T(d)),
next(NULL), d_func(func) {}
~linked_list_node()
{
if(d_func)
d_func(data); //execute custom function for reclaiming pointer-type
else
delete data;
}
};
然后,您可以通过创建linked_list_node
类型的实例时传递正确的模板参数实例化不同的版本。例如,
linked_list_node<MyPtr*> node(FooPtr); //creates the specialized ptr version
linked_list_node<MyEnum> node(FooEnum); //creates a non-ptr version of the node
模板专业化是最好的答案,并且将工作做好,只要你不混合类型的节点。但是,如果你想混合链接节点的类型,让我告诉你如何去做。首先,没有简单的模板解决方案。由于严格的类型限制,您必须一起键入您的链接节点。
甲相当普遍的解决方案是构建变体类(其可以容纳具有变化类型的一个值,并且总是知道哪一个)。例如,Qt有一个QVariant类。 Boost有boost::any。
这是一个完整的示例实现,它使用可以容纳任何类型的自定义变体类。我可以处理你建议的对象指针和枚举,但可以扩展来保存更多。
这将打印“删除目标文件”一旦一个例子:
#include <iostream>
int
main(int argc, char **argv)
{
LinkedList<VariantExample> elementObj(new ExampleObj);
LinkedList<VariantExample> elementEnum(enumOne);
elementEnum.setNext(elementObj);
}
// VariantExample class. Have a look at [QVariant][4] to see how a fairly
// complete interface could look like.
struct ExampleObj
{
};
enum ExampleEnum
{
enumOne,
enumTwo
};
struct VariantExample
{
ExampleObj* obj; // or better boost::shared_ptr<ExampleObj> obj
ExampleEnum en;
bool is_obj;
bool is_enum;
VariantExample() : obj(0), is_obj(false), is_enum(false) {}
// implicit conversion constructors
VariantExample(ExampleObj* obj_) : is_obj(true), is_enum(false)
{ obj = obj_;
}
VariantExample(ExampleEnum en_) : obj(0), is_obj(false), is_enum(true)
{ en = en_;
}
// Not needed when using boost::shared_ptr above
void
destroy()
{
if(is_obj && obj)
{
std::cout << "delete obj" << std::endl;
delete obj;
}
}
};
// The linked list template class which handles variant classes with a destroy()
// method (see VariantExample).
template
<
typename _type_ = VariantExample
>
struct LinkedList
{
LinkedList* m_next;
_type_ m_variant;
explicit
LinkedList(_type_ variant_) : m_next(0), m_variant(variant_){ }
void
setNext(LinkedList& next_){ m_next = &next_; }
// Not needed when using boost::shared_ptr above
~LinkedList()
{
m_variant.destroy();
}
};
因为调用一次当链表的析构函数被调用elementObj的破坏方法,输出的“删除目标文件”中出现一次。同样,由于您对删除/所有权非常具体,因此此示例具有销毁方法/接口。它将在LinkedList类的析构函数中显式调用。一个更好的所有权模式可以用ie来实现。 boost::shared_ptr。那么你不需要手动销毁它。顺便说一下,它有助于阅读conversion constructors。
// the first parameter becomes boost::shared_ptr<ExampleObj>(new ExampleObj))
// and is deleted when LinkedList is destroyed. See code comments above.
LinkedList<> elementObj(new ExampleObj);
最后请注意,您必须有一个变体类才能容纳您的LinkedList链中可能出现的所有类型。最后,由于“下一个”指针类型,两个不同的LinkedList Variant类型将无法工作。这将不兼容。
脚注: 类型约束如何防止一个简单的解决方案吗?想象一下,链接节点的“下一个”指针类型不仅仅是裸模板名称,它是一个快捷方式,但实际上还包括模板参数 - 最终作为编译器用来判断类型兼容性的类型符号。
您是否想制作不同类型的链接列表? – Xeo 2012-03-07 19:26:18
为了确保我正确理解这一点,你想有一个LinkedList3210,然后能够推动Blah *进入它并让LinkedList自动销毁并释放链表的内容指向的所有对象?这似乎是班上不应该做的事情。如果你想保持一个对象存活,但是你已经将它推入列表并且该列表已被删除,该怎么办?也许你正在寻找某种智能指针? (像Boost智能指针。) – Corbin 2012-03-07 19:28:16
@Xeo是的,但我的其中一种类型将枚举(静态),另一种类型将指向事物(动态)。结构已经存在,我正在努力,虽然现在将它转换为模板 – gardian06 2012-03-07 19:28:49