Overloading output stream in generic Stack class

i am using stack to store student object and overload output stream

Page 1 of 1

2 Replies - 1663 Views - Last Post: 24 September 2010 - 06:05 AM Rate Topic: -----

#1 Guest_Mandi*


Reputation:

Overloading output stream in generic Stack class

Posted 23 September 2010 - 07:09 PM

#include <iostream>
using namespace std;

class Student
{
    private:
        string name;
    public:

        Student()
        {
            setStudentName("John");
        }

        Student(string name)
        {
            setStudentName(name);
        }

        string getStudentName()
        {
            return name;
        }

        void setStudentName(string name)
        {
            this->name=name;
        }

};


template<typename Obj>
class Stack
{

private:
	Obj* data;
	int size;
	int capacity;

public:

Stack():size(0),capacity(16)
{
	data = new Obj[capacity];
}

bool empty()
{
	return (size == 0);
}

void push(Obj value)
{
	data[size++]=value;
}

Obj pop()
{
	return data[--size];
}

friend ostream& operator<<(ostream& stream, Stack<Obj*> &c)
{
    while(!c->empty())
    {
        Obj Stu=c->pop();
        stream<<Stu->getStudentName()<<endl;
    }
    return stream;
}

};


int main()
{
    //Student Objects
    Student s1("Harry");
    Student s2("Peter");
    Student s3("James");
    Student s4("Candy");

    //Stack for student list
    Stack<Student*> *StudentStack=new Stack<Student*>;

    //Pushing student into stack
    StudentStack->push(&s1);
    StudentStack->push(&s2);
    StudentStack->push(&s3);
    StudentStack->push(&s4);

    //over loading output stream to show stack
    cout<<StudentStack;

    return 0;
}




I am using a generic stack to store student objects.then i am overloading output stream to display the list of student stored in stack. but my above code is giving garbage value as output. so plz tell me how to display the name of student stored in stack using overloading of output stream......

Is This A Good Question/Topic? 0

Replies To: Overloading output stream in generic Stack class

#2 eker676  Icon User is offline

  • Software Engineer
  • member icon

Reputation: 378
  • View blog
  • Posts: 1,833
  • Joined: 18-April 09

Re: Overloading output stream in generic Stack class

Posted 23 September 2010 - 07:45 PM

This works:
template <typename Obj>
friend ostream& operator<<(ostream& stream, Stack<Obj*>* c)
{
    while(!c->empty())
    {
        Obj* Stu=c->pop();
        stream<<Stu->getStudentName()<<endl;
    }
    return stream;
}

Was This Post Helpful? 1
  • +
  • -

#3 Anarion  Icon User is offline

  • The Persian Coder
  • member icon

Reputation: 282
  • View blog
  • Posts: 1,456
  • Joined: 16-May 09

Re: Overloading output stream in generic Stack class

Posted 24 September 2010 - 06:05 AM

You haven't defined a destructor for your stack class. You are allocating memory in constructor, so you have to define a proper destructor as well:
~Stack() {
    delete[] data;
}


And, by removing the use of pointers in your stack class and also adding const correctness, this is achieved:
#include <iostream>
#include <string>
using namespace std;

class Student {
private:
    string name;
public:

    Student() {
        setStudentName("John");
    }

    Student(const string& name) {
        setStudentName(name);
    }

    string getStudentName() {
        return name;
    }

    void setStudentName(const string& name) {
        this->name=name;
    }

};


template<typename Obj>
class Stack {

private:
    Obj* data;
    int size;
    int capacity;

public:

    Stack():size(0),capacity(16) {
        data = new Obj[capacity];
    }

    ~Stack() {
        delete[] data;
    }

    bool empty() {
        return (size == 0);
    }

    void push(const Obj& value) {
        data[size++]=value;
    }

    Obj pop() {
        return data[--size];
    }

    friend ostream& operator<<(ostream& stream, Stack<Obj> &c) {
        while(!c.empty()) {
            Obj Stu=c.pop();
            stream<<Stu.getStudentName()<<endl;
        }
        return stream;
    }

};


int main() {
    //Student Objects
    Student s1("Harry");
    Student s2("Peter");
    Student s3("James");
    Student s4("Candy");

    //Stack for student list
    Stack<Student> StudentStack;

    //Pushing student into stack
    StudentStack.push(s1);
    StudentStack.push(s2);
    StudentStack.push(s3);
    StudentStack.push(s4);

    //over loading output stream to show stack
    cout<<StudentStack;

    return 0;
}


Let's talk about what happens if you still store pointers. The main function would be:
Student *s1 = new Student("Harry");
Stack<Student*> StudentStack;
StudentStack.push(s1);
delete s1;
cout<<StudentStack;


Basically, you are storing pointers to memory locations, which may be released somewhere in the program(for example, if you use temporary Student objects). When you push such objects to your stack, you are only storing memory locations. When that certain object reaches it's end of scope, it gets deleted and that location goes out of your program's bounds. Look at this line:
StudentStack.push(s1);

In this line, a student object's address is stored in stack and then it is deleted in the next line... but you still have the pointer to this location in your stack! Let's print the stack right now...
... the program crashes ... Why?!
Because you are trying to access a memory location out of bounds of your program.

Conclusion: You should store copies of these objects in the stack, not their address. This makes sure these objects are under control and do not get deleted when the stack object still exists.

Hope this story helped you understand the problem.

Edit: I guess [this tutorial] can help you.

This post has been edited by Anarion: 24 September 2010 - 06:08 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1