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)
. 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). By passing by value, you are telling your code to copy the whole of v1
into a new object inside of 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.
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.
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
. Instead, you likely see the error on this line: 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.
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. 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. 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.