我有一个通用链表,可以处理各种类型的数据,包括对象和指向对象的指针等,但是当我从派生自抽象类的类中插入对象时,使用列表时会遇到麻烦。

我有一个称为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的问题少得多,您就可以大大减少内存问题。

08-05 18:19