简体   繁体   中英

output operator overloading for queue class C++

I am trying to overload the << operator in order to print objects of classes, I tried making a friend function of the operator and then declaring it in below the Queue class, I have not written anything inside the code block here is what I have, it wont compile, it will crash instantly, thanks in advance.

#include <string>
#include <vector>
#include <iostream>
using namespace std;


class Employee{

protected:
    long empId;
    string empName;
    string email;
public:
        Employee(){}
        Employee(long i, string n){
         empName = n,
         empId =i;
         email = "Unknown";
    }
};

class Student{

protected:
    long stId;
    int year;
    string email;
    string schoolName;
public:
    Student(){}
    Student(long i, int y, string sn){
    stId = i;
    year =y;
    email = "Unknown";
    schoolName=sn;
    }
};

template<class T>
class Queue{
protected:
    vector<T> theQ;
public:
    void Push(T item);
    T pop();
    void ReadAnItem();
    void PrintQ();
    **template<T>** edit
    friend ostream& operator<< (ostream& is, const Queue<T>& theQ);
};


template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ){
        **os << theQ.Print();** Edit
    return os;
}
template<class T>
void Queue<T>::ReadAnItem(){
    T item;
    cout << "Enter the data please: " << endl;
    cin >> item;
    Push(item);
}

template<class T>
void Queue<T>::Push(T item){
    theQ.front() = item;
}

template<class T>
void Queue<T>::PrintQ(){
    cout << "The content of the array is as follows: " << endl;
    for (int i=0; i< theQ.size(); i++){
        cout << theQ[i] << **endl;** I get an "invalid overload of endl"
    }
}

You should declare that friend function as a template:

template <class U>
friend ostream& operator<< (ostream& is, const Queue<U>& theQ);

Your operator<< function is a template function, so note that inside friend declaration:

friend ostream& operator<< <T>(ostream& is, const Queue<T>& theQ);

This is not the as Andy's variant, as Andy's variant allows this:

#include <iostream>


template <class T>
class A
{
public:
        A(T d): data(d){}

private:
        // friend is any template instance of function foo, and not just foo<T>!
        template <class U>
        friend void foo(A<U>& t);

        T data;
};


A<int> ai(1);


template <class T>
void foo(A<T>& t)
{
        // A<int> will accept foo<double> as friend
        std::cout << ai.data << std::endl;
        std::cout << t.data << std::endl;
}

int main()
{
        A<double> ad(2);
        foo(ad);
        return 0;

}

However, in my case, you need to add few forward declarations, in order to make this right:

#include <iostream>


// 2. But before that you need to forward-declare your class, so the function
// can know about the class.
template <class T>
class A;


// 1. You need to forward-declare your foo function...
template <class T>
void foo(A<T>& t);


template <class T>
class A
{
public:
        A(T d): data(d){}

private:

        friend void foo<T>(A<T>& t);


        T data;
};


A<int> ai(1);


template <class T>
void foo(A<T>& t)
{
        // error: ‘int A<int>::data’ is private within this context
        //std::cout << ai.data << std::endl;
        std::cout << t.data << std::endl;
}

int main()
{
        A<double> ad(2);
        foo(ad);

}

Here's your code, but you need more work to do:

#include <string>
#include <vector>
#include <iostream>
using namespace std;


class Employee{

protected:
    long empId;
    string empName;
    string email;
public:
        Employee(){}
        Employee(long i, string n){
         empName = n,
         empId =i;
         email = "Unknown";
    }
};

class Student{

protected:
    long stId;
    int year;
    string email;
    string schoolName;
public:
    Student(){}
    Student(long i, int y, string sn){
    stId = i;
    year =y;
    email = "Unknown";
    schoolName=sn;
    }
};

template<class T>
class Queue;

template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ);


template<class T>
class Queue{
protected:
    vector<T> theQ;
public:
    void Push(T item);
    T pop();
    void ReadAnItem();
    void PrintQ() const;
 friend ostream& operator<< <T> (ostream& is, const Queue<T>& theQ);
};


template<class T>
ostream& operator<< (ostream& os, const Queue<T>& theQ){
        // I will just use this, but it should receive ostream
        theQ.PrintQ();
        return os;
}
template<class T>
void Queue<T>::ReadAnItem(){
    T item;
    cout << "Enter the data please: " << endl;
    cin >> item;
    Push(item);
}

template<class T>
void Queue<T>::Push(T item){
    // this aint gonna work! Use std::deque and push_front! theQ.front() = item;
}

template<class T>
void Queue<T>::PrintQ() const{
    cout << "The content of the array is as follows: " << endl;
    for (int i=0; i< theQ.size(); i++){
        // You need to overlload operator<< for student to make this work! cout << theQ[i] << endl;
    }
}

int main()
{
        Queue<Student> s;
      s.Push(Student());

        std::cout << s;
        return 0;
}

Note - this code is not perfect (nor good), it just shows you how to solve this particular problem. You need to move body of PrintQ() method to operator<< or to make your PrintQ to accept and return ostream& . Also, I've already marked it as a const , as it doesn't change state of the class. Also, you don't have operator<< for student, so you are not able to output it into the ostream& . Also, vector.first() = s will always wipe your first element (it will copy s into the first element of the vector using operator= ), or it will fail, if there's no first element. I'm sure there's other bugs, but these are only that I saw while trying your program.

Edit

For each different class, you need to have different operator<< . So, change the Student to:

class Student{

protected:
    long stId;
    int year;
    string email;
    string schoolName;
    friend ostream& operator<<(ostream& os, const Student& s);
public:
    Student(){}
    Student(long i, int y, string sn){
    stId = i;
    year =y;
    email = "Unknown";
    schoolName=sn;
    }
};

and add another operator<< body:

ostream& operator<<(ostream& os, const Student& s)
{
   os << s.stId << s.year << s.email << std::endl;
   return os;
}

Also, do this for Employee . And you should consider moving common fields from Student and Employee to base class Person .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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