How do I add objects of different types to a Linked List C++

  • (2 Pages)
  • +
  • 1
  • 2

20 Replies - 612 Views - Last Post: 03 October 2012 - 08:54 AM Rate Topic: -----

#16 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

Re: How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 10:09 PM

At the top of my main program I create a LinkedList<Package>* p; It should be around line 4. I just didn't copy the whole thing again to paste on here.
int main()
{
    LinkedList<Package> package_list; //Should be new list that all packages will be stored in
    LinkedList<Package>* p;  //I create p here

    //declares all the variables that are used to describe packages
    int number,type,length,width,height,depth,weight;
    int counter = 0;
    string sender, receiver;
    float charge, average, totalprofit = 0;

    cin>>number;

    while ( counter < number )
    {	
        cin>>type;
        cin>>sender;
        cin>>receiver;
        cin>>length;
        cin>>width;

       if (type == 2)
        {
            package_list.insert_front(two_D(sender,receiver,length,width));
     
        }
        else
        {
            if (type == 3)
            {
                cin>>height;
                cin>>weight;
                package_list.insert_front(three_D(sender,receiver,length,width,height,weight));
         

            }
            else
            {
                cin>>height;
                cin>>depth;
                cin>>weight;
                package_list.insert_front(four_D(sender,receiver,length,width,height,depth,weight));
               
            }
        }
		
        counter++;           
    }
    counter = 0;

    //In this loop I need functions to access the position at counter
    //and then get the appropriate values: sender,receiver, and the charge
    while ( counter < number)
    {
        p = package_list.getAtPtr(counter);
        cout<<"#"<<counter<<":"<<"  From "<<p->getsender()<<" to "<<p->getreceiver()<<endl;
        cout<<"#"<<counter<<":"<<"  From "<<<" to "<<endl;
        cout<<"$ "<<getcharge()<<endl;
        totalprofit = totalprofit + p->getcharge();

        counter++;
    }

    cout<<"Total Profit = "<<totalprofit<<endl;
    cout<<"Average = "<<totalprofit/number<<endl;

    return 0;
}


I just tried it with the pointer created as Package* p and it says: Error - assigning to 'Package *' from incompatible type 'LinkedList<Package> *'. Would my LinkedList also need to be a derived class of package so that it could use the get() functions? Would I have to un-template it to do so?
Was This Post Helpful? 0
  • +
  • -

#17 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 3169
  • View blog
  • Posts: 9,595
  • Joined: 05-May 12

Re: How do I add objects of different types to a Linked List C++

Posted 30 September 2012 - 10:55 PM

Sorry, I was thinking of a different linked list implementation. How about:
Package package = package_list.at(counter);


Was This Post Helpful? 0
  • +
  • -

#18 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5643
  • View blog
  • Posts: 12,359
  • Joined: 16-October 07

Re: How do I add objects of different types to a Linked List C++

Posted 01 October 2012 - 04:50 AM

You know, you're torturing yourself with that linked list. You are given the number of items. An array would work...

Also, simply taking your Node and calling it a LinkedList doesn't make it so. Making a template class or throwing pointer syntax about doesn't fix logic.

When I saw you'd started to put in pointers, I thought you'd figured out one of your major errors. Alas, no. To spell it out:
#include <iostream>

using namespace std;

class Package {
protected:
	int length, width;
	string sender, receiver;
	float charge;

public:
	Package() : sender(""), receiver(""), length(0), width(0){}
	Package(string s, string r, int l, int w) : sender(s),receiver(r),length(l),width(w){ }
	virtual string getsender(){return sender;}
	virtual string getreceiver(){return receiver;}
	// this will never work
	// virtual float getcharge(){return charge;}
	virtual float getCharge(){return charge;}

};


class two_D : public Package {
protected:
	int area;

public:
	two_D(string s, string r, int l, int w) : Package(s,r,l,w){}
	float getCharge() {
		area = length * width;
		charge = area * .05;
		return charge;
	}
};

class three_D : public two_D {
protected:
	int height, volume, weight;
	
public:
	three_D(string s, string r, int l, int w, int h, int m) : two_D(s,r,l,w) {
		height = h;
		weight = m;
	}

	float getCharge() {
		volume = area * height;
		charge = (volume*.02)+(weight*2.15);
		return charge;
	}
};

void print(Package &item) {
	cout << "Package: ";
	cout << "  From " << item.getsender() << " to " << item.getreceiver() << endl;
	cout <<"$ "<< item.getCharge() << endl;
	cout << endl;
}

void print(two_D &item) {
	cout << "two_D: ";
	cout << "  From " << item.getsender() << " to " << item.getreceiver() << endl;
	cout <<"$ "<< item.getCharge() << endl;
	cout << endl;
}

void print(three_D &item) {
	cout << "three_D: ";
	cout << "  From " << item.getsender() << " to " << item.getreceiver() << endl;
	cout <<"$ "<< item.getCharge() << endl;
	cout << endl;
}

int main() {
	two_D item1("Zapp","Leela", 10, 20);
	three_D item2("Dr.Zoidberg","Mom",14,28,30,18);
	Package item3(item1);
	Package item4(item2);
	two_D item5(item2);
	
	print(item1);
	print(item2);
	print(item3);
	print(item4);
	print(item5);
	

	return 0;
}




Results:
two_D:   From Zapp to Leela
$ 10

three_D:   From Dr.Zoidberg to Mom
$ 69.9

Package:   From Zapp to Leela
$ 1.4013e-45

Package:   From Dr.Zoidberg to Mom
$ 1.4013e-45

two_D:   From Dr.Zoidberg to Mom
$ 19.6



What's going on here is that your parent classes are NOT the same as your children. If you take one of your children and store it as Package, it is now Package. The way to avoid this is to store a pointer to the object in question.

e.g.
Package *item1 = new two_D("Zapp","Leela", 10, 20);
Package *item2 = new three_D("Dr.Zoidberg","Mom",14,28,30,18);
	
print(*item1); // print(Package &) will be called by this
print(*item2);

delete item1;
delete item2;




Results:
Package:   From Zapp to Leela
$ 10

Package:   From Dr.Zoidberg to Mom
$ 69.9




If you honestly want to do a LinkedList, make one with just the methods you need, the types you need, and node and list separate. I'd go with something like:
class LinkedList {
public:
	LinkedList();
	~LinkedList();
	void add(string s, string r, int l, int w);
	void add(string s, string r, int l, int w, int h, int m);
	void add(string s, string r, int l, int w, int h, int m, int d);
	bool getFirst(Package *&);
	bool getNext(Package *&);
private:
	void add(Package *);
	struct Node {
		Package *data;
		Node *next;
		Node(Package *d, Node *n) : data(d), node(n) { }
	};
	Node *head, *current;
};



However, an array simply makes more sense...
struct Packages {
	Package **items;
	const int size;
	Packages(int);
	~Packages();
};

Package *readData(std::istream &in);

int main() {
	int number;
	cin>>number;
	Packages packages(number);
	
	for(int i=0; i<packages.size; i++) {
		packages.items[i] = readData(cin);
	}
	
	float totalprofit = 0;
	for(int i=0; i<packages.size; i++) {
		Package *p = packages.items[i];
		cout<<"#"<<counter<<":"<<"  From "<<p->getsender()<<" to "<<p->getreceiver()<<endl;
		cout<<"#"<<counter<<":"<<"  From "<<<" to "<<endl;
		cout<<"$ "<<getCharge()<<endl;
		totalprofit += p->getCharge();
	}

	cout<<"Total Profit = "<<totalprofit<<endl;
	cout<<"Average = "<<totalprofit/number<<endl;

	return 0;
}



Hope this helps.
Was This Post Helpful? 1
  • +
  • -

#19 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

Re: How do I add objects of different types to a Linked List C++

Posted 01 October 2012 - 09:08 AM

Thank you very much I really appreciate it that answer was very clear and concise and helped me shore up my problems. How did you come to the conclusion that an array list would be the best choice when first seeing the problem. Was it intuition or did something signal to you which path to take?
Was This Post Helpful? 0
  • +
  • -

#20 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5643
  • View blog
  • Posts: 12,359
  • Joined: 16-October 07

Re: How do I add objects of different types to a Linked List C++

Posted 01 October 2012 - 09:26 AM

The reason to use a linked list, or any collection, is because you don't know for sure how many objects you'll need to store. If you know how many objects you need to store, then an array becomes an option.

Arrays are simply storage, offering no functionality beyond that, so if a collection class offers other functionality you require, you're still usually better off using one. However, if the choice is writing your own dynamically allocated, node based, collection from scratch or just using an array, the array starts to look pretty good.
Was This Post Helpful? 1
  • +
  • -

#21 sseabass92  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 30-September 12

Re: How do I add objects of different types to a Linked List C++

Posted 03 October 2012 - 08:54 AM

Thanks for your response. So I tried the array and I am still getting 2 errors: Error - assigning to 'Packages *' from incompatible type 'Package *'
and: Error - cannot initialize a variable of type 'Package *' with an lvalue of type 'Packages *'


I sort of understand why I'm getting them but I am unsure of how to fix it. It is happening because packages.item is of type packages. Then I try to create a pointer Package* p to the items. But Package is not of type packages. I tried making Package a derived class of Packages it will eliminate the first error but not the second one.

The errors are in the main part of my program I included everything just to show what I have.


#include <iostream>
#include <string>

using namespace std;

//This is my Array structure which holds packages
struct Packages{

	//creates a pointer to a pointer which points to the items
	Packages **items;

	//keeps the size of my array
    const int size;

    //Constructor which creates the number of packages int
    Packages(int);

    ~Packages();
};

//This is my base class package which other package classes are derived from
//If I add a constructor to my Packages struct and make this class a derivation of it
//it can possibly eliminate 1 error
//-------------------------------------------
class Package 
{
    protected:
    int length, width;         // All packages 
    string sender, receiver;   // have these variables
    float charge;              // points to next package of list

    public:

        virtual ~Package(){}

        Package() : length(0), width(0),sender(""), receiver(""){}

        Package(string s, string r, int l, int w) : length(l),width(w),sender(s),receiver(r){ }

        virtual string getsender(){return sender;}
        virtual string getreceiver(){return receiver;}

        //Used to get the charge for each package type in the list
        virtual float getCharge(){return charge;}

};

//-------------------------------------------
class two_D : public Package
{
    protected:
        int area;

    public:

    two_D(string s, string r, int l, int w) : Package(s,r,l,w){}

    float getCharge()
    {
        area = length * width;
        charge = area * .05;
        return charge;
    }
	
};

//-------------------------------------------
class three_D : public two_D
{
    protected:
    int height, volume, weight;
	
    public:

        three_D(string s, string r, int l, int w, int h, int m) : two_D(s,r,l,w)
        {
            height = h;
            weight = m;
        }

        float getCharge()
       {
            volume = length * width * height;
            charge = (volume*.02)+(weight*2.15);
            return charge;
        }

};

//-------------------------------------------
class four_D : public three_D
{
    private:
        int depth, h_volume;

    public:

        four_D(string s, string r, int l, int w, int h, int m, int d) : three_D(s,r,l,w,h,m)
        {
            depth = d;
        }

        float getCharge()
        {
            h_volume = length * width * height * depth;
            charge = (h_volume*.01)+(weight*3.14)+42.42;
            return charge;
        }

};

//creates a pointer of type Package that points to the data read in.
Package *readData(std::istream &in);

int main() {

    int number,counter = 0;

    cin>>number;

    //creates an array of type packages of size number (user input)
    Packages packages(number);

    //for loop runs for number of packages
    //Adds data to position i (package 0-number)
    for(int i=0; i < packages.size; i++) {

        //Error here because I am trying to add data of type Package into an array that is of type Packages
        //If I make package a derived class of Packages it removes the error
        packages.items[i] = readData(cin);

    }

    float totalprofit = 0;

    for(int i=0; i < packages.size; i++) {

        //creates a pointer of type package that will point to the items in my Packages array
        //error here
        Package *p = packages.items[i];

        //Gets sender and receiver data from current position i in packages array
        cout<<"#"<<counter<<":"<<"  From "<<p->getsender()<<" to "<<p->getreceiver()<<endl;

        //gets the charge of package at the current position i in packages array
        cout<<"$ "<<p->getCharge()<<endl;

        totalprofit += p->getCharge();
    }

 	cout<<"Total Profit = "<<totalprofit<<endl;

    cout<<"Average = "<<totalprofit/number<<endl;

 	return 0;

}



If I change the line: Package *readData(std::istream &in); to Packages *readData(std::istream &in); it eliminates the first error but the second one remains. What exactly is that line of code doing? Does it create a pointer of type package to the data which is read into my array?
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2