Storing values in a container - c++

I'm trying to read two values from a file and store them in my class called God. God has two data members, name and mythology. I wish to store the values in a list<God> (the god and its respective mythology) and then print them out. Here is my code so far:
#include <iostream>
#include <fstream>
#include <list>
#include <string>
using namespace std;
class God {
string name;
string mythology;
public:
God(string& a, string& b) {
name=a;
mythology =b;
}
friend ostream& operator<<( ostream& os,const God&);
};
void read_gods(list<God>& s) {
string gname, gmyth;
//reading values from file
ifstream inFile;
inFile.open("gods.txt");
while(!inFile.eof()) {
inFile >> gname >> gmyth ;
s.push_back(God(gname, gmyth));
}
}
ostream& operator<<( ostream& os,const God& god) {
return os << god.name << god.mythology;
}
int main() {
//container:
list<God> Godmyth;
read_gods(Godmyth);
cout << Godmyth;
return 0;
}
If for example I read in Zeus, Greek then how would I be able to access them?
The error I'm receiving is:
error: cannot bind 'std::ostream {aka std::basic_ostream<char>}' lvalue to 'std::basic_ostream<char>&&'|

You should write either operator << or some member function for class God that outputs its data members.
For example
class God
{
public:
std::ostream & out( std::ostream &os ) const
{
return os << name << ": " << mythology;
}
//...
};
Or
class God
{
public:
friend std::ostream & operator <<( std::ostream &, const God & );
//...
};
std::ostream & operator <<( std::ostream &os, const God &god )
{
return os << god.name << ": " << god.mythology;
}
In this case instead of invalid statement
cout << Godmyth << endl;
you could write
for ( const God &god : Godmyth ) std::cout << god << std::endl;
Or if you simply want to access the data members then you should write getters.
For example
class God
{
public:
std::string GetName() const { return name; }
std::string GetMythology() const { return mythology; }
//...

There is no overloaded operator<< allowing printing std::list's content using std::cout.
What you can do?
As #Vlad mentioned, you can write
for ( const God &god : Godmyth )
std::cout << god << '\n';
Alternatively, you can write your own operator<<:
template<typename T>
std::ostream& operator<< (std::ostream &os, const std::list<T> &_list){
os << "[\n";
for ( const auto &item : _list )
os << item << ";\n";
return os << ']';
}

Related

error: 'VD<Class1> Class2::data' is private within this context

I'm having some problems with my code. I declared in the .h two friend functions which are:
#ifndef CLASS2_H
#define CLASS2_H
#include "class1.h"
#include <string>
#include <iostream>
using namespace std;
class Class2{
private:
VD<Class1> data; //Vector of objects of Class1
VD<int> number; //Vector of int
public:
Constructor();
friend istream & operator >> (istream & i, const Class1 & other);
friend ostream & operator << (ostream &o, const Class1 & other);
};
#endif
And the .cpp is:
istream & operator >> (istream & i,Class2 & other){
string n;
Class1 ing;
getline(i,n);
while(!i.eof()){
i >> ing;
otro.data.Insert(ing,otro.data.size()-1);
}
return i;
}
ostream & operator << (ostream &o, const Ingredientes & otro){
for(int i = 0; i < otro.datos.size(); i++){
o << other.data[i];
}
return o;
}
So, the error that I'm getting is:
error: 'VD Class2::data' is private within this context. I declared the functions of operator >> y << friend but I doesn't make any sense that compiler says to me that I can't access to the private data. Any help please?
You seem to be very new at C++, and you seem to be doing quite complex things, while you're not understanding the basics yet. Please find a tutorial or so.
A few things:
using namespace std; is -especially in a header- never a good idea. It's like you're going on holiday, but bring along everything in your house. Refer to standard namespace functions using std::.
an istream& operator>>() cannot put anything in an object that is declared const.
using vec.insert(obj, vec.size()-1) is reinventing one of the most essential funcitons of std::vector: push_back()...
while (!i.eof()) is not good, because eof is not set until after the read past the end.
there's no string& operator>>(string& str, Class1& obj) function defined. We have std::stringstream for that.
To show how you could realize some of this, I'm going to write some example code. Please don't just copy it, but try to understand it.
test.txt
1 2 3 4
5 6 7 8
main.cpp
#include <vector>
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
template <typename T>
using VD = std::vector<T>;
class Class1 {
private:
int d;
public:
friend std::istream& operator>> (std::istream& i, Class1& obj) {
i >> obj.d;
return i;
}
friend std::ostream& operator<< (std::ostream& o, const Class1& obj) {
o << obj.d;
return o;
}
};
class Class2 {
private:
VD<Class1> data{}; //Vector of objects of Class1
public:
void Clear() { data.clear(); }
friend std::istream& operator>> (std::istream& i, Class2& obj) {
std::string line;
std::getline(i, line);
std::istringstream iss(line);
Class1 ing;
while (iss >> ing) {
obj.data.push_back(ing);
}
return i;
}
friend std::ostream& operator<< (std::ostream& o, const Class2& obj) {
for (auto const& cl1 : obj.data) {
o << cl1 << " ";
}
return o;
}
};
int main() {
Class2 cl2;
std::ifstream ifs;
ifs.open("test.txt");
if (ifs.is_open()) {
ifs >> cl2;
}
std::cout << "first line: " << cl2 << '\n';
cl2.Clear();
if (ifs.is_open()) {
ifs >> cl2;
}
std::cout << "second line: " << cl2 << '\n';
ifs.close();
}

Global overload of operator<< does not work, why?

I have learnt the operator<< can be overloaded by making it a friend function of class.
For example,
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
friend std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
};
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}
one
two
This seems to work as expected.
But, I'm unable to understand why the same isn't working for a global overload.
#include <iostream>
#include <ostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
stackoverflowstackoverflow
Expected the strings to be separated by a newline, but didn't work as expected.
Your operator using
std::cout << "stackoverflow";
requires a user-defined conversion from an object of the type const char * (after the implicit conversion of the string literal to pointer to its first character) to an object of the type std::string.
However the standard basic_ostream class has already an operator that does not require such a conversion
template<class charT, class traits>
basic_ostream<charT, traits>& operator<<(basic_ostream<charT, traits>&, const char*);
So this operator is called instead of your operator.
Moreover within your operator
std::ostream & operator<<(std::ostream & os, const std::string & s)
{
os << s << '\n';
return os;
}
there is recursive calls of itself.
Your could define your operator the following way
#include <iostream>
#include <string>
std::ostream & operator<<(std::ostream & os, const char *s)
{
return std::operator <<( os, s ) << '\n';
}
int main()
{
std::cout << "stackoverflow";
std::cout << "stackoverflow";
}
and get the expected result
stackoverflow
stackoverflow
Note that "stackoverflow" is of type const char[], but not std::string. That means your overload won't be invoked, but the one from standard library (operator<<(std::basic_ostream) is invoked, because it's an exact match and doesn't require the implicit conversion from const char[] to std::string.
template< class Traits >
basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os,
const char* s );
BTW: It could be found because of ADL.
You can overload globally, but "stackoverflow" is not a std::string, so yours isn't used.
(And there already is such an overload in the standard library.)
To see that it works, move your first overload out of the class definition and make it a non-friend.
The only reason it has to be declared friend is that you have declared it inside the class definition, so it would be a member function otherwise.
This will work as you expect:
struct Test
{
std::string d_data;
Test(const std::string & data) : d_data{data} {}
};
std::ostream & operator<<(std::ostream & ostr, const Test & obj)
{
ostr << obj.d_data << '\n';
return ostr;
}
int main()
{
Test t1("one");
std::cout << t1;
Test t2("two");
std::cout << t2;
}

Overriding of operator<< in c++

I'm working on a project for my school in C++
I have 2 class : Employe and Teacher.
Teacher derived from Employe and has overrides of his functions.
We override the operator << to print some information of the Employes or Teachers.
Each class has a const int attribute LevelAcces_.
For Employe, it's 5 and for Teacher it's 20.
when I create an Teacher in my main.cpp, I call the override of operator<< of Teacher to print his information.
So this function is called :
ostream& operator<<(ostream& os, const Teacher& pTeacher){
os << (pTeacher);
return os;
}
But, the function calls itself with the line "os << (pTeacher);" and does a loop that causes a stack overflow.
I want that the line "os << (pTeacher)" calls the operator<< of my class Employe and not of my class Teacher.
Override of operator<< in Employe :
ostream& operator<<(ostream& os, const Employe& pEmploye){
os << "Name: " << pEmploye.name_ << endl;
os << "Class: " << pEmploye.getClass() << endl;
os << "LevelAcces: " << pEmploye.getLevelAccess() << endl;
return os;
}
I tried to cast my Teacher into Employe but when it prints the message, LevelAcces is 5 (and I want 20, because my Employe is a Teacher).
I also tried to use Employe::operator<< but operator<< is not a member of Employe so it doesn't work...
So, here is my question :
How can I do to use my operator<< of Employe in my operator<< of Teacher and print the right information (LevelAccess = 20 and not 5) ?
I was also thinking of "virtual" but our professor tells us that there is not need to use this word.
Thanks in advance :)
Here is a more complete code :
main.cpp:
Teacher Garry("Garry");
cout << Garry << endl;
Employe.cpp :
#include "Employe.h"
using namespace std;
Employe::Employe(){
name_ = "";
}
Employe::Employe(string pName){
name_ = pName;
}
string Employe::getName() const{
return name_;
}
unsigned int Employe::getLevelAccess() const{
return levelAccess_;
}
string Employe::getClass() const{
return typeid(*this).name();
}
ostream& operator<<(ostream& os, const Employe& pEmploye){
os << "Name: " << pEmploye.name_ << endl;
os << "Class: " << pEmploye.getClass() << endl;
os << "LevelAcces: " << pEmploye.getLevelAccess() << endl;
return os;
}
With this in Employe.h :
private:
static const unsigned int LevelAccess_ = 5;
Teacher.cpp :
#include "teacher.h"
using namespace std;
Teacher::Teacher(string pName){
nom_ = pName;
}
unsigned int Teacher::getLevelAccess() const{
return(Employe::getLevelAccess() + accessTeacher_);
}
string Teacher::getClass() const{
return typeid(*this).name();
}
ostream& operator<<(ostream& os, const Teacher& pTeacher){
os << (pTeacher);
return os;
}
With this is Teacher.h :
static const unsigned int accesTeacher_ = 15;
What I'd do is the following: define only one
ostream& operator<<(ostream& os, const Employe& pEmploye)
{
return pEmploye.display(os);
}
for the base of the hierarchy,
in which you call a protected member function virtual display() that is overridden by each derived class and to which the display is being delegated. This is sometime call the NVI (non-virtual interface) idiom. It works like this:
class Employee
{
// ...
friend ostream& operator<<(ostream& os, const Employee& pEmployee)
{
return pEmployee.display(os);
}
protected:
virtual ostream& display(ostream& os) const
{
// implement it here
return os;
}
};
class Teacher: public Employee
{
// ....
protected:
ostream& display(ostream& os) const override
{
// implement it here
return os;
}
};
You can use a cast:
os << static_cast<const Employe &>(pTeacher);
The & is important.
To make the call to the member function call Teacher::getLevelAccess() from an Employe reference, you have to make that function virtual. (Do this in teacher.h). getClass() should be virtual also.
NB. You keep saying things like "Override of operator<< in Employe :" , however you do not have overloaded operator<< in Employe . You have a free function which takes Employe as argument.

error: declaration of 'operator<<' as non-function|

I am having a really hard time with overloading the << operator. I am working on a homework assignment where I can only modify certain portions of the code. Before you ask, I AM stuck using a struct instead of a class. Here are the portions of the affected code:
The calling function is:
/*
* Write a CSV report listing each course and its enrollment.
*/
void generateReport (ostream& reportFile,
int numCourses,
Course* courses)
{
for (int i = 0; i < numCourses; ++i)
{
//courses is an array of "Course" structs
reportFile << courses[i] << endl;
}
}
Here is the .h file:
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <string>
struct Course {
std::string name;
int maxEnrollment;
int enrollment;
Course();
Course(std::string cName);
std::ostream& operator << (ostream &out, const Course &c);
};
#endif
Here is the .cpp file:
#include "course.h"
using namespace std;
Course::Course()
{
name = "";
maxEnrollment = 0;
enrollment = 0;
}
Course::Course(string cName)
{
name = cName;
maxEnrollment = 0;
enrollment = 0;
}
// send course to file
ostream& Course::operator << (ostream &out, const Course &c)
{
out << c.name << "," << c.enrollment << endl;
return out;
}
Here is the error message I keep getting:
error: declaration of 'operator<<' as non-function|
I have been searching the internet for hours and tried lots of different approaches to solve this problem with no success.
Please help!!
I tried a couple of different methods to fix this based on advice. Here are two methods I tried which did not work:
Method 1:
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <string>
struct Course {
std::string name;
int maxEnrollment;
int enrollment;
Course();
Course(std::string cName);
};
//Moved this outside the struct
std::ostream& operator << (ostream &out, const Course &c);
#endif
Method 2 (also failed to change error):
#include "course.h"
using namespace std;
Course::Course()
{
name = "";
maxEnrollment = 0;
enrollment = 0;
}
Course::Course(string cName)
{
name = cName;
maxEnrollment = 0;
enrollment = 0;
}
std::ostream& operator << (ostream &out, const Course &c);
// send course to file
ostream& Course::operator << (ostream &out, const Course &c)
{
out << c.name << "," << c.enrollment << endl;
return out;
}
RE-EDIT--------------------------------------------------------
After some of the comments and help, here is my current code:
In the .h file:
#ifndef COURSE_H
#define COURSE_H
#include <iostream>
#include <string>
struct Course {
std::string name;
int maxEnrollment;
int enrollment;
Course();
Course(std::string cName);
std::ostream& operator << (std::ostream &out, const Course &c);
};
#endif
In the .cpp file:
#include "course.h"
using namespace std;
Course::Course()
{
name = "";
maxEnrollment = 0;
enrollment = 0;
}
Course::Course(string cName)
{
name = cName;
maxEnrollment = 0;
enrollment = 0;
}
// send course to file
ostream& operator << (ostream &out, const Course &c)
{
out << c.name << "," << c.enrollment << endl;
return out;
}
You forgot to include <ostream> and the namespace specifier std:: in your argument, which leads into your error.
Read on if you want to hear about your next error:
std::ostream& operator << (std::ostream &out, const Course &c);
This means that you define an operator which should work on a current instance of a Course as left hand side (*this), since it is defined as a member. This would lead into an operator that has one left hand side and two right hand sides, which isn't possible.
You need to define the operator as a non-member function, since the left hand side should be an ostream& and not Course&.
std::ostream& operator << (std::ostream &out, const Course &c);
should be
friend std::ostream& operator << (std::ostream &out, const Course &c);
And
std::ostream& Course::operator << (std::ostream &out, const Course &c) // Not a member of Course
{
should be
std::ostream& operator << (std::ostream &out, const Course &c)
{
Since it is not a member of Course.
std::ostream& operator << (ostream &out, const Course &c); inside the Course declaration, must be declared as friend, otherwise it cannot take two parameters.
also, the fist parameter must be std::ostream& and not just ostream&

C++ equivalent of Java's toString?

I'd like to control what is written to a stream, i.e. cout, for an object of a custom class. Is that possible in C++? In Java you could override the toString() method for similar purpose.
In C++ you can overload operator<< for ostream and your custom class:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
This way you can output instances of your class on streams:
A x = ...;
std::cout << x << std::endl;
In case your operator<< wants to print out internals of class A and really needs access to its private and protected members you could also declare it as a friend function:
class A {
private:
friend std::ostream& operator<<(std::ostream&, const A&);
int j;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.j << ")";
}
You can also do it this way, allowing polymorphism:
class Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Base: " << b << "; ";
}
private:
int b;
};
class Derived : public Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Derived: " << d << "; ";
}
private:
int d;
}
std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }
In C++11, to_string is finally added to the standard.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
As an extension to what John said, if you want to extract the string representation and store it in a std::string do this:
#include <sstream>
// ...
// Suppose a class A
A a;
std::stringstream sstream;
sstream << a;
std::string s = sstream.str(); // or you could use sstream >> s but that would skip out whitespace
std::stringstream is located in the <sstream> header.
The question has been answered. But I wanted to add a concrete example.
class Point{
public:
Point(int theX, int theY) :x(theX), y(theY)
{}
// Print the object
friend ostream& operator <<(ostream& outputStream, const Point& p);
private:
int x;
int y;
};
ostream& operator <<(ostream& outputStream, const Point& p){
int posX = p.x;
int posY = p.y;
outputStream << "x="<<posX<<","<<"y="<<posY;
return outputStream;
}
This example requires understanding operator overload.