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.
Related
I'm trying to overload the ">>" operator so i can read and store a new Atlas<Animal *> from the keyboard.
The atlas template class has a list in which i'm storing pointers to each Animal object. Here is the code:
class Animal {
protected:
std::string m_name;
public:
Animal() {}
Animal (std::string name): m_name {name} {}
virtual void set_name(std::string name) {m_name = name;}
virtual std::string get_name () {return m_name;}
virtual std::string regn() const { return "???"; }
virtual ~Animal(){
cout << "Destructor animal"<<'\n';}
friend istream& operator >> (istream &in, Animal* k){
in>> k->m_name;
return in;}
}; //pointers to objects from this class will be stored in Atlas2;
//declaration for >> operator
template <class T>
class Atlas2;
template<typename T>
std::istream& operator>>(std::istream& in, const Atlas2<T>& A);
// Template class
template<class T>
class Atlas2{
public:
int nr_pesti;
int m_length;
std::list<T> pages;
Atlas2(){m_length = 0; nr_pesti = 0;}
~Atlas2(){}
void adauga(T data);
Atlas2 operator += (const T& data){
this->m_length++;
this->pages.push_back(data);
return *this;}
friend std::istream& operator>> <> (std::istream& in, const Atlas2<T>& A);
};
template <class T>
istream operator>> (istream &in, const Atlas2<T> &A)
{
in >> A.m_length;
for (int i=1; i<=A.m_length; i++){
T data = new T;
cin >> data;
A.pages.push_back(data);}
return in;
}
template <class T>
void Atlas2<T>::adauga(T data){m_length = m_length+1;
pages.push_back(data);}
// here's the main:
int main(){
Atlas2<Animal *> Atlas3;
cin >> Atlas3;
return 0;}
What am I doing wrong here? I get this error when compiling:
ambiguous overload for 'operator>>' (operand types are 'std::istream' {aka 'std::basic_istream<char>'} and 'Atlas2<Animal*>') at line 58 (Where i type cin>>Atlas3) and these Warnings for the >> operator in the template class : note: candidate: 'std::istream& operator>>(std::istream&, const Atlas2<T>&) [with T = Animal*; std::istream = std::basic_istream<char>]'
I have a class IPrintable which is a template and a class which derives from it - Date. I want to add the operator >> to the template but keep getting an error:
source.cpp(16): error C2259: 'Date': cannot instantiate abstract class
source.cpp(16): note: due to following members:
source.cpp(16): note: 'void IPrintable<Date>::toIs(std::istream &)': is abstract
iprintable.h(19): note: see declaration of 'IPrintable<Date>::toIs'
I have successfully added the << operator to the template this way:
virtual void toOs(ostream& os) const = 0;
friend ostream& operator << (ostream& output, const IPrintable& toPrint) {
toPrint.toOs(output);
return output;
}
And then I have declared virtual void toOs(ostream& os) const = 0; to date.h and implemented it in date.cpp.
This is my IPrintable.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
template <class T>
class IPrintable {
private:
public:
virtual void toOs(ostream& os) const = 0;
friend ostream& operator << (ostream& output, const IPrintable& toPrint) {
toPrint.toOs(output);
return output;
}
virtual void toIs(istream& input) = 0;
friend istream& operator >> (istream& input, IPrintable& toSet) {
toSet.toIs(input);
return input;
}
};
This is the declaration of in Date.h, under public:
virtual void toOs(ostream& output) const;
virtual void toIS(istream& input);
This is the implementation of the << (toOs) and >> (toIs) in Date.cpp:
void Date::toOs(ostream& output) const {
if (!isLeapYear(this->getDay(), this->getMonth(), this->getYear())) {
cout << "Not a leap year";
return;
}
output << getDay() << "/" << getMonth() << "/" << getYear();
}
void Date::toIS(istream& input) {
int index;
string str;
input >> str;
index = str.find('/');
this->setDay(stoi(str.substr(0, index)));
str = str.substr(index + 1);
index = str.find('/');
this->setMonth(stoi(str.substr(0, index)));
str = str.substr(index + 1);
this->setYear(stoi(str));
}
Please, if any more information is needed please let me know and I will do my best to provide it.
Thanks!
Your Date::toIS has a capital S, while your IPrintable::toIs does not. If you add override to the declaration of Date::toIS, you would see that it doesn't actually override anything.
I need to add operator<< to make my cout working.
Code template.cpp:
#include "maptemplate.h"
int main(void)
{
typedef unsigned int ID; //Identification number of Employee
map_template<ID,Employee> Database; //Database of employees
Database.Add(761028073,Employee("Jan Kowalski","salesman",28)); //Add first employee: name: Jan Kowalski, position: salseman, age: 28,
Database.Add(510212881,Employee("Adam Nowak","storekeeper",54)); //Add second employee: name: Adam Nowak, position: storekeeper, age: 54
Database.Add(730505129,Employee("Anna Zaradna","secretary",32)); //Add third employee: name: Anna Zaradna, position: secretary, age: 32
//cout << Database << endl; //Print databese
//map_template<ID,Employee> NewDatabase = Database; //Make a copy of database
Employee* pE;
pE = Database.Find(510212881); //Find employee using its ID
pE->Position = "salesman"; //Modify the position of employee
pE = Database.Find(761028073); //Find employee using its ID
pE->Age = 29; //Modify the age of employee
//Database = NewDatabase; //Update original database
///cout << Database << endl; //Print original database
cout<<"Wszystko dziala"<<endl;
}
Code: template.h
#include <iostream>
#include <vector>
using namespace std;
// Początek klasy Employee bez template
class Employee
{
private:
public:
Employee(string Name, string Position, int Age);
string Name;
int Age;
string Position;
}; // koniec klasy employee
// Dodanie pól Name, Age, Position
Employee::Employee(string Name, string Position, int Age)
{
this->Name = Name;
this->Age = Age;
this->Position = Position;
}
template <class Key, class T> // template <klucze, dane pracownikow>
class map_template
{
private:
vector<Key> keys; // vector do przechowywania unikalnych kluczy pracowników
vector<T> content; // vector do przechowywania danych pracowników
public:
map_template()
{
}
void Add(Key key, T t);
T* Find(Key key);
}; // koniec klasy map_template
// Dodanie do bazy (Add)
template <class Key, class T>
void map_template<Key, T>::Add(Key key, T t)
{
keys.push_back(key);
content.push_back(t);
}
// Szukanie w bazie (Find)
template <class Key, class T>
T* map_template<Key, T>::Find(Key key)
{
for (unsigned int i = 0; i < keys.size(); i++)
if (keys[i] == key)
{
return &content.at(i);
}
return nullptr;
}
I was thinking how i should look at it. Its my first time using templates so i dont know how operator<< should look like.
Was thinking about something like:
friend ostream & operator<< (ostream & s, teamplate<something>);
But dont really know how to add it.
I need
cout << Database << endl;
to work properly.
Sorry for some polish language comments.
Edit:
I tried putting this friend declaration in the class Employee but i keep getting errors :(
code:
class Employee
{
private:
public:
Employee(string Name, string Position, int Age);
string Name;
int Age;
string Position;
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
}
errors:
maptemplate.h:49:63: error: ‘Key’ was not declared in this scope
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
^~~
maptemplate.h:49:68: error: ‘T’ was not declared in this scope
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
^
maptemplate.h:49:69: error: template argument 1 is invalid
friend ostream &operator << (ostream &out, const map_template<Key, T> &map);
^
maptemplate.h:49:69: error: template argument 2 is invalid
maptemplate.h: In instantiation of ‘std::ostream& operator<<(std::ostream&, const
map_template<Key, T>&):
Should i change the declaration or what? I know that Key and T are in private. Maybe thats the case?
Anyone can help?
I'm a begginer so :/
You want:
template <class Key, class T>
std::ostream& operator << (std::ostream& out, const map_template<Key, T>& map) {
// your logic on how to output the map here...
return out;
}
so your operator<< will work with map_template of any specialization.
Obviously, your friend approach would also be suitable, plus you would actually drop the unnecessary template line. If you place your operator << declaration inside your class, this:
friend std::ostream& operator << (std::ostream& out, const map_template<Key, T>& map) {
// your logic on how to output the map here..
return out;
}
will do just fine. Notice the lack of repeated template <class Key, class T>. Inside your class - those template types are visible and thus you can use them.
For example, I've written a class called Length:
class Length {
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
void print(float value) {
std::cout << value;
}
void computeStuff(float value) {
//do the computing
}
int main() {
Length width;
width.setValue(5);
std::cout << width; // <-- this is actually just an example
//what I actually want is:
print(width); // print 5
//or perhaps even
computeStuff(width);
return 0;
}
Now how to make width return value_ or 5?
Technically, width is not an instance name, it's a name of a variable of type Length. You can change your code to retrieve a variable in two ways:
Add a friend operator << for Length that does the printing, or
Add an implicit conversion operator from Length to float.
The first approach works only for output. You cannot pull the value directly:
friend ostream& operator <<(ostream& out, const Length& len) {
out << len.value_;
return out;
}
The second approach looks like this:
class Length {
...
public:
operator float() const { return value_; }
};
You must overload operator<< for your custom type, something like:
class Length
{
..
friend std::ostream& operator<<(std::ostream& os, const Length& o);
..
}
std::ostream& operator<<(std::ostream& os, const Length& o)
{
os << o.value_;
return os;
}
Mind that this
must be non member
is nothing special , just an operator overload applied to a standard way of inserting things into stream of <iostream>
You need to define an operator() method to print the value 5.
You need to overload the << operator for your class. You could also use a function to do the operator's work.
Operator <<
#include <iostream>
class Length {
friend std::ostream& operator<<(std::ostream& os, const Length& l);
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
std::ostream& operator<<(std::ostream& os, const Length& l)
{
os << l.value_;
return os;
}
int main() {
Length width;
width.setValue(5);
std::cout << width << std::endl; // print 5
return 0;
}
function:
#include <iostream>
class Length {
friend std::ostream& print(std::ostream &,const Length &l);
public:
void setValue(float);
private:
float value_;
};
void
Length::setValue(float newValue) {
value_ = newValue;
}
std::ostream& print(std::ostream &os, const Length &l)
{
os << l.value_;
return os;
}
int main() {
Length width;
width.setValue(5);
print(std::cout, width) << std::endl;
return 0;
}
I'm practicing templates in Visual Studio 2013 from a not so well written C++ book and I receive the following compiler errors respectively, "error C4430: missing type specifier - int assumed. Note: C++ does not support default-int" and "error C2143: syntax error : missing ',' before '<'".
Both refer me to line 10 which is...
std::ostream& operator<< (std::ostream&, const Array<T>&);
The desired behavior of my code is to show the creation and destruction of temporary Animal objects using templates.
The troubleshooting steps I have tried so far include substituting std::iostream& with int in my return type and first parameter type of line 10. After doing so the error messages remained the same. This seemed to suggest that the problem may be the second parameter type. I then added the keyword typename to the second parameter of my overloading operator function (operator<<) on line 10 and the error still persisted.
Line 10 can be found in the header file below.
//Array.h
#ifndef ARRAY_H
#define ARRAY_H
#include <iostream>
#include "Animal.h"
const int DefaultSize = 3;
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
template <typename T> // declare the template and the paramenter
class Array // the class being parameterized
{
public:
Array(int itsSize = DefaultSize);
Array(const Array &rhs);
~Array() { delete[] pType; }
// operators
Array& operator=(const Array&);
T& operator[](int offSet) { return pType[offSet]; }
const T& operator[](int offSet) const { return pType[offSet]; }
// accessors
int GetSize() const { return itsSize; }
// friend function
friend std::ostream& operator<< (std::ostream&, const Array<T>&);
private:
T *pType;
int itsSize;
};
template <typename T>
Array<T>::Array(int size = DefaultSize) :itsSize(size)
{
pType = new T[size];
for (int i = 0; i < size; i++)
pType[i] = static_cast<T>(0);
}
Array<Animal>::Array(int AnimalArraySize) :itsSize(AnimalArraySize)
{
pType = new Animal[AnimalArraySize];
}
template <typename T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.GetSzie();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
}
template <typename T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if (this == &rhs)
return *this;
delete[] pType;
itsSize = rhs.GetSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
pType[i] = rhs[i];
return *this;
}
template <typename T>
std::ostream& operator<< (std::ostream& output, const Array<T> &theArray)
{
for (int i = 0; i < theArray.GetSize(); i++)
output << "[" << i << "]" << theArray[i] << std::endl;
return output;
}
#endif
Here's the rest of my code from my book for your reference.
//Animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
#include <iostream>
class Animal
{
public:
// constructors
Animal();
Animal(int);
~Animal();
// accessors
int GetWeight() const { return itsWeight; }
void SetWeight(int theWeight) { itsWeight = theWeight; }
// friend operators
friend std::ostream& operator<<(std::ostream&, const Animal&);
private:
int itsWeight;
};
#endif
//Animal.cpp
#include "Animal.h"
#include <iostream>
Animal::Animal() :itsWeight(0)
{
std::cout << "animal() ";
}
Animal::Animal(int weight) : itsWeight(weight)
{
std::cout << "animal(int) ";
}
Animal::~Animal()
{
std::cout << "Destroyed an animal...";
}
//Main.cpp
#include <iostream>
#include "Animal.h"
#include "Array.h"
std::ostream& operator<<(std::ostream&, const Animal&);
void IntFillFunction(Array<int>& theArray);
void AnimalFillFunction(Array<Animal>& theArray);
int main()
{
Array<int> intArray;
Array<Animal> animalArray;
IntFillFunction(intArray);
AnimalFillFunction(animalArray);
std::cout << "intArray...\n" << intArray;
std::cout << "\nanimalArray...\n" << animalArray << std::endl;
std::cin.get();
return 0;
}
std::ostream& operator<<(std::ostream& theStream, const Animal& theAnimal)
{
theStream << theAnimal.GetWeight();
return theStream;
}
void IntFillFunction(Array<int>& theArray)
{
bool Stop = false;
int offset, value;
while (!Stop)
{
std::cout << "Enter an offset (0-9) and a value. ";
std::cout << "(-1 to stop): ";
std::cin >> offset >> value;
if (offset < 0)
break;
if (offset > 9)
{
std::cout << "***Please use values between 0 and 9.***\n";
continue;
}
theArray[offset] = value;
}
}
void AnimalFillFunction(Array<Animal>& theArray)
{
Animal *pAnimal;
for (int i = 0; i < theArray.GetSize(); i++)
{
pAnimal = new Animal(i * 10);
theArray[i] = *pAnimal;
delete pAnimal;
}
}
I've tried my best to keep this question on topic by providing you with the desired behavior of the program, a specific problem or error and the shortest code necessary to reproduce it. All of which are requirements for debugging help as documented in the Help Center page.
I'm new to this website, and if my question is still off-topic, please let me know how I can change my question to be more on topic or inform me of a better place to ask my question. - Thank you
This function is declared before the Array class is declared (i.e., the compiler has never seen that type and doesn't know what it is, hence your error).
template<typename> class Array; // Add this forward declaration
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
Edit
I just noticed that the operator<< is declared before the Array class and as a friend function within the Array class. You could just remove the declaration at the top.
Edit 2
Array.h
I removed the following items
#include "Animal.h"
template <typename T>
std::ostream& operator<< (std::ostream&, const Array<T>&);
Array<Animal>::Array(int AnimalArraySize) :itsSize(AnimalArraySize)
{
pType = new Animal[AnimalArraySize];
}
Updated the friend function declartion to be
template<typename T> // This is not a member function so must be declared as a template
friend std::ostream& operator<< (std::ostream&, const Array<T>&);
Animal.h
This class has the friend function but it's not implemented in the cpp file. I moved the definition from the main.cpp into Animal.cpp