我有一个通用链表,可以处理各种类型的数据,包括对象和指向对象的指针等,但是当我从派生自抽象类的类中插入对象时,使用列表时会遇到麻烦。
我有一个称为Vehicle的抽象类,以及carr和truck的2个类,我可以做这样的事情:
list<vehicle> lv;
vehicle * v1;
vehicle * v2;
v1 = new carr;
v2 = new truck;
cin >> *v1 >> *v2;
//But when I try to insert in the list
lv.insertEnd(*v1);
我有错误:
无法分配抽象类型“车辆”的对象
编译器表明错误出在我写的部分的链表代码的insertEnd方法中:
newNode->item = new Item;
这是项目的一部分,我需要列出车辆,车辆可以是卡车,卡车等。我使用指针来实现一组车辆,但是我尝试使用车辆列表来实现。 。
你能帮助我吗?
编辑:
该项目在我的链表中,我将显示我的insertEnd方法:
template <class Item>
void list<Item>::insertEnd(const Item& item)
{
node<Item> *newNode= new node<Item>;
newNode->item = new Item;
*(newNode->item) = item;
newNode->next = 0;
if(head == 0)
{
head = newNode;
tail = newNode;
_size++;
}
else
{
novoNo->prev = tail;
tail->next = newNode;
tail = newNode;
_size++;
}
}
最佳答案
您试图按值将项目存储在链接列表中。按值使用项会破坏多态性:只有指针或引用才是多态性。
这是您看到的错误的原因是,您正在此处取消引用指针:lv.insertEnd(*v1)
。以这种方式传递值将导致C ++将复制构造函数用于insertEnd
中指定的类型,以使对象位于insertEnd
函数内部(检查代码:insertEnd
的参数类型肯定是在模板中指定的类型-在此处为vehicle
。通过传递值,您告诉您的代码将整个v1
复制到insertEnd
内部的新对象中。这很不容易,因为vehicle
是抽象类:因为它是抽象的,所以不能使用其复制构造函数来创建功能齐全的对象。
这种阴影实际上是在这里发生的事情:您无法按值传递对象并期望它们是多态的。如果没有看到此错误,则可能会发生slice your object的情况,调试起来甚至更糟。执行@billz建议的操作并使用智能指针。
编辑:看到您添加了insertEnd代码后,您通过引用传递了代码,这里有一个附录:编译器不会在insertEnd
中调用复制构造函数。相反,您可能会在以下行中看到错误:newNode->item = new Item
。在这里,您可以看到尝试实例化抽象类的位置。用'Item
'替换单词'vehicle
'-这就是您正在使用模板的方式-您可以很清楚地看到它。
无论如何,将引用传递给解除引用的指针确实是非常痛苦且容易出错的事情。引入错误太容易了:如果您在代码中的任何地方delete
v1,就像一个优秀的程序员一样(伟大的程序员使用自动指针),您可能会留下参考悬而未决的情况:某天指向内存中的空间-例如重要的人正在运行您的代码时-可能在您的引用不知道的情况下充满了垃圾。我的朋友,这就是疯狂的方式。
这就是为什么智能指针是C ++程序员最好的朋友的原因:一旦您了解了它们在做什么,您几乎可以忽略这种混乱,而可以通过值自由传递它们。他们的生命周期合同定义非常明确,可以自己清理,并且是例外安全的。只要您不设置参考周期(在日常使用中,问题的发生率要比通过引用传递取消引用的指针)或try to use auto_ptr in a standard container PLEASE READ THIS LINK AND UNDERSTAND IT的问题少得多,您就可以大大减少内存问题。