简体   繁体   English

C ++链表-插入对象

[英]c++ Linked List - Insert Object

I have a generic linked list that works with various types of data including objects and pointers to objects, etc, but i'm having trouble working with the list when I insert objects from a class that is derived from an abstract class . 我有一个通用的链表,可以处理各种类型的数据,包括对象和指向对象的指针等,但是当我从派生自抽象类的类中插入对象时,使用列表时会遇到麻烦。

I have an abstract class called vehicle and 2 classes that are carr and truck and I can do something like this: 我有一个称为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);

I have the error: 我有错误:

cannot allocate an object of abstract type 'vehicle' 无法分配抽象类型“车辆”的对象

And the compiler show that the error is in the insertEnd method of my linked list code in the part where I write: 编译器表明错误出在我写的部分的链表代码的insertEnd方法中:

newNode->item = new Item;

This a part of a project where I need to have a list of vehicles and the vehicles can be carrs, trucks, etc. I have the group of vehicles implemented with pointers to pointers but i'm trying to do this with a list of vehicles. 这是项目的一部分,我需要列出车辆,车辆可以是卡车,卡车等。我使用指针来实现一组车辆,但我尝试使用车辆列表来实现。 。

Can you help me? 你能帮助我吗?

EDIT: The item is in my linked list, i'll show my insertEnd method: 编辑:该项目在我的链表中,我将显示我的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++;
    }
}

You are trying to store an item by value in your linked list. 您试图按值将项目存储在链接列表中。 Using items by value breaks polymorphism: only pointers or references are polymorphic. 按值使用项会破坏多态性:只有指针或引用才是多态性。

The reason this is the error you see is that you are dereferencing your pointer here: lv.insertEnd(*v1) . 这是您看到的错误的原因是,您正在此处取消引用指针: lv.insertEnd(*v1) Passing in a value this way will cause C++ to use the copy constructor for the type specified in insertEnd to make the object inside of your insertEnd function (check your code: the type of the parameter to insertEnd is surely the type specified in your template - which is vehicle here). 以这种方式传递值将导致C ++将copy构造函数用于insertEnd指定的类型,以使对象位于insertEnd函数内部(检查代码: insertEnd参数的类型肯定是模板中指定的类型-在这里是vehicle )。 By passing by value, you are telling your code to copy the whole of v1 into a new object inside of insertEnd . 通过传递值,您可以告诉代码将整个v1复制到insertEnd内部的新对象中。 This falls apart, because vehicle is an abstract class: its copy constructor cannot be used to make a fully functional object, because it's abstract. 这是分散的,因为vehicle是一个抽象类:因为它是抽象的,所以其复制构造函数不能用于制作功能齐全的对象。

This sort of shadows what's really going on here: you can't pass around objects by value and expect them to be polymorphic. 这种阴影实际上是在这里发生的事情:您无法按值传递对象并期望它们是多态的。 If you don't see this error, what will likely happen is that you will likely slice your object , which can be even worse to debug. 如果您没有看到此错误,则可能发生的情况是您可能会对对象进行切片 ,而调试起来甚至更糟。 Do what @billz recommends and use a smart pointer. 执行@billz建议的操作并使用智能指针。

EDIT: after seeing your addition of your insertEnd code, where you are passing by reference, there is an addendum: the compiler is not going to call the copy constructor in insertEnd . 编辑:看到您添加了insertEnd代码后,您通过引用传递了代码,这里有一个附录:编译器不会insertEnd调用复制构造insertEnd Instead, you likely see the error on this line: newNode->item = new Item . 相反,您可能会在以下行看到错误: newNode->item = new Item Here you can see where you are trying to instantiate the abstract class. 在这里,您可以看到尝试实例化抽象类的位置。 Replace the word ' Item ' with ' vehicle ' - that's what you're doing with your template - and you can see it very clearly. 用“ vehicle ”代替“ Item ”一词-这就是您使用模板所做的工作-您可以很清楚地看到它。

In any case, passing-by-reference to a dereferenced pointer is a very painful and error-prone thing indeed. 无论如何,将引用传递给解除引用的指针确实是非常痛苦且容易出错的事情。 It's way too easy to introduce errors: if you delete v1 anywhere in your code, like a good programmer does (great ones use auto pointers), you are likely to leave your reference dangling: pointing to a space in memory that someday - like when someone important is running your code - may be filled with garbage without your reference knowing it. 引入错误太容易了:如果像优秀的程序员一样在代码中的任何地方delete v1(伟大的程序员都使用自动指针),则很可能使引用悬而未决:指向某天内存中的空间,例如一个重要的人正在运行您的代码-可能在您的引用不知道的情况下充满了垃圾。 This be the way to madness, my friend. 我的朋友,这就是疯狂的方式。

This is exactly why smart pointers are a C++ programmer's best friend: once you understand what they're doing, you can all but ignore this sort of mess and just pass them around by value freely. 这就是为什么智能指针是C ++程序员最好的朋友的原因:一旦您了解了它们在做什么,您几乎可以忽略这种混乱,而可以通过自由传递它们。 Their lifecycle contract is very well defined, they clean up after themselves, they are exception safe. 他们的生命周期合同定义非常明确,可以自己清理,并且是例外安全的。 As long as you don't set up reference cycles - which is far less problematic in everyday usage than passing a dereferenced pointer by reference - or try to use auto_ptr in a standard container PLEASE READ THIS LINK AND UNDERSTAND IT , you've vastly reduced your memory problems. 只要您不设置参考周期(在日常使用中,问题就比通过引用传递已取消引用的指针要少得多),或者尝试在标准容器中使用auto_ptr,请仔细阅读此链接并了解它 ,您已经大大减少了你的记忆问题。

you need to use pointer in this case, the better way is to use smart pointer. 在这种情况下,您需要使用指针,更好的方法是使用智能指针。

std::list<std::shared_ptr<vehicle> > lv;

In your list<vehicle> lv; 在您的list<vehicle> lv; , lv only contains vehicle type object, lv.insertEnd(*v1); lv仅包含vehicle类型对象lv.insertEnd(*v1); will slice your object to vehicle type which is not allow as vehicle is abstract class. 会将您的对象切成车辆类型,因为车辆是抽象类,所以不允许。

since one cannot instantiate an object of abstract types, it failed to construct the object for insertion. 由于无法实例化抽象类型的对象,因此无法构造用于插入的对象。

Also, the copy construction semantics of stl does not support polymorphic use. 同样,stl的副本构造语义也不支持多态使用。 a "vehicle" list should only contain vehicle objects, not car objects. “车辆”列表应仅包含车辆对象,而不应包含车辆对象。

You have to use container of pointers. 您必须使用指针容器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM