Operator Overloading: Ostream/Istream - c++

I'm having a bit of trouble with a lab assignment for my C++ class.
Basically, I'm trying to get the "cout << w3 << endl;" to work, so that when I run the program the console says "16". I've figured out that I need to use an ostream overload operation but I have no idea where to put it or how to use it, because my professor never spoke about it.
Unfortunately, I HAVE to use the format "cout << w3" and not "cout << w3.num". The latter would be so much quicker and easier, I know, but that's not my decision since the assignment necessitates I type it in the former way.
main.cpp:
#include <iostream>
#include "weight.h"
using namespace std;
int main( ) {
weight w1(6);
weight w2(10);
weight w3;
w3=w1+w2;
cout << w3 << endl;
}
weight.h:
#ifndef WEIGHT_H
#define WEIGHT_H
#include <iostream>
using namespace std;
class weight
{
public:
int num;
weight();
weight(int);
weight operator+(weight);
};
#endif WEIGHT_H
weight.cpp:
#include "weight.h"
#include <iostream>
weight::weight()
{
}
weight::weight(int x)
{
num = x;
}
weight weight::operator+(weight obj)
{
weight newWeight;
newWeight.num = num + obj.num;
return(newWeight);
}
TL;DR: how can I make the "cout << w3" line in main.cpp work by overloading the ostream operation?
Thanks in advance!

Make a friend function in your class
friend ostream & operator << (ostream& ,const weight&);
define it as :
ostream & operator << (ostream& os,const weight& w)
{
os<<w.num;
return os;
}
See here

class weight
{
public:
int num;
friend std::ostream& operator<< (std::ostream& os, weight const& w)
{
return os << w.num;
}
// ...
};

Alternately, make a to_string method that converts weight.num to string ;-)

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();
}

Why this usage string with ostream cause stackoverflow?

I just wondering why this code is incorrect ? It constantly call Foo constructor and cause stack overflow after sometime.
#include <iostream>
using namespace std;
class Foo
{
std::string str;
public:
Foo(const string& s) : str(s)
{
cout << "Foo constructor" << endl;
}
friend ostream& operator<<(ostream& os,const Foo& foo);
};
ostream& operator<<(ostream& os,const Foo& foo)
{
os << foo.str;
return os;
}
int main()
{
Foo foo{"Hello"};
cout << foo;
cin.get();
}
I know, I know it is ok to write
cout << foo.str << endl;
or os << foo.str.c_str();
but I want to know why this error happens..
The program use std::string and its output operator but does not include the header <string>: when using <string> you need to include that header. The fact that std::string seems to be defined by including <iostream> is insufficient. It is also not portable: a different implementation may choose to only declare but not defined std::string (a declaration is needed, though, as some IOStream members to use the type std::string).
If the output operator for std::string isn't found, the expression
out << foo.str
is interpreted as as
out << Foo(foo.str)
as there is an output operator for Foo. Of course, that does result in an infinite recursion.

Friend function defining an ostream operator

I would like to define an ostream operator to let me easily output variables of type alglib::complex. To provide a working example without including the alglib library I'll instead overload the output of complex<double> below (this clarification because of an earlier version of the question). In the header file "my_class.h" I have
using namespace std;
#include <complex>
#include <iostream>
class my_class {
public:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
void output(complex<double>);
my_class() {}
~my_class() {}
};
And in the source file "my_class.cpp" I have
#include "my_class.h"
void my_class::output(complex<double> cd) {
cout << cd << endl;
}
Finally I have a main method file "run_my_class.cpp":
#include "my_class.h"
int main(int argc, const char* argv[]) {
my_class obj;
complex<double> cd=complex<double>(1.0,-1.0);
obj.output(cd);
}
I try to compile using
g++ -c my_class.cpp
but this gives me the error
my_class.h:9:62: error: ‘std::ostream& my_class::operator<<(std::ostream&, std::complex<double>)’ must take exactly one argument
ostream& operator << (std::ostream& os, complex<double> a) {
However, if I define the operator as a friend, namely friend ostream& operator << (std::ostream& os, complex<double> a), it compiles and I compile the main method:
g++ run_my_class.cpp my_class.o -o run_my_class
And it works as it should. However this is not what it seems the friend keyword is for. Is there a better way to make this work?
Since operator << will be called on an std::ostream, you cannot define this procedure as a member function for my_class, you have to define it as a global function, since it's an operation for std::ostream, not my_class.
By putting the friend keyword into the declaration, you are saying that you want to declare the operator << as a friend global function (not a member function!). The C++ standard lets you put the definition of the friend function there, but it won't be a member function. It is the same as the following, which is more clear:
#include <complex>
#include <iostream>
class my_class {
public:
friend ostream& operator << (std::ostream& os, complex<double> a);
void output(complex<double>);
my_class() {}
~my_class() {}
};
std::ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
As it was already pointed out in the comments, the usage of friend is not necessary here.
Irrelevant to the question, but please be aware that resolving namespaces in a header file is generally a really-really bad idea, since all other files including it will implicitly resolve that namespace too. It can easily lead to vexing compilation errors in the long run.
I wouldn't call it a better way but a more clear way.
Here's your stream operator again:
ostream& operator << (std::ostream& os, complex<double> a) {
os << "(" << real(a) << "," << imag(a) << ")";
return os;
}
Its first parameter is the output stream. Since you do not have access to the output stream, you can't use the output stream operator as a member function unless you make it a friend of the class.
If you want to want to avoid using friend you can always define it as a function external to the class, and that is the most common way.

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&

OOP C++ first compiler error

Please help this newbie, here's my code:
#include <iostream>
using namespace std;
class Complex {
private:
float r, i;
public:
Complex(float rr, float ii) : r(rr), i (ii) {}
float GiveRe () { return r; }
float GiveIm () { return i; }
void Setit (float rr, float ii) {
r = rr;
i = ii;
}
};
Complex a(10, 20);
Complex sumit (Complex &ref) {
static Complex sum (0, 0);
sum.Setit(sum.GiveRe() + ref.GiveRe(), sum.GiveIm() + ref.GiveIm());
return sum;
}
int main () {
Complex sumvalue = sumit (a);
cout << sumvalue << endl;
return 0;
}
error: no match for 'operator<<' in 'std::cout << sumvalue'.
The program should output the sum of a complex number.
cout can't tell what you want to output, you need to specify the operator<< in the class or make it possible to implicitly convert your class to a compatible type.
http://www.cplusplus.com/reference/iostream/ostream/operator%3C%3C/
Rudolf Mühlbauer's code as implemented in your class:
Add this somewhere within the class header:
friend ostream& operator<<(ostream& out, const Complex& compl);
and this below the header:
ostream& operator<<(ostream& out, const Complex& compl)
{
return out << compl.r << "/" << compl.i;
}
Implementation should be changed to suit your exact needs.
Complex doesn't have an operator <<
ostream& Complex::operator << ( ostream& os )
{
// use os << field/method here to out put
return os;
}
Also if complex can be displayed to console in different ways, then you should think of using methods to display instead of cout <<
void Complex::DisplayToConsole()
{
std::cout << r << " " << i << '\n';
}
You have to overload the "<<" operator for Complex type.
#include <iostream>
using namespace std;
class Complex {
private:
float r, i;
public:
Complex(float rr, float ii) : r(rr), i (ii) {}
float GiveRe () { return r; }
float GiveIm () { return i; }
void Setit (float rr, float ii) {
r = rr;
i = ii;
}
};
ostream& operator<<(ostream& os, Complex& c)
{
float i;
os<<c.GiveRe();
if(c.GiveIm() < 0){
os<<"-j"<<c.GiveIm()*(-1);
}else{
os<<"+j"<<c.GiveIm();
}
return os;
}
Complex a(10, 20);
Complex sumit (Complex &ref) {
static Complex sum (0, 0);
sum.Setit(sum.GiveRe() + ref.GiveRe(), sum.GiveIm() + ref.GiveIm());
return sum;
}
int main () {
Complex sumvalue = sumit (a);
cout << sumvalue << endl;
return 0;
}
A complete minimal example:
#include <iostream>
using namespace std;
class C {
public:
int r, l;
// if the operator needs access to private fields:
friend ostream& operator<< (ostream&, const C&);
};
ostream& operator << (ostream& stream, const C& c) {
stream << c.r << "--" << c.l;
return stream;
}
int main() {
C c;
c.l = 1;
c.r = 2;
cout << c << endl;
}
C++ allows you to define operators. The STL uses the << operator for output, and the whole istream/ostream class hierarchy uses this operator to input/output.
Operators are implemented as functions, but always follow a very specific syntax. As in the example, ostream& operator << (ostream&, const MYTYPEHERE&) is the way to define ostream << operators.
When C++ encounters a statement, it has to deduce the types of all operands, and find (quite magically, indeed) a solution to the question: given my operands and operators, can i find a typing such that the statement gets valid?
These ofstream operators are defined for all basic types somewhere in <iostream>, so if you write cout << 10, the compiler finds an operator ostream& operator<< (ostream&, int).
If you want to be able to use userdefined types in this game, you have to define the operators. otherwise, a statement cout << sometype will not be valid. This is also the reason for the harsh compiler errors sometimes found in C++: "Well, i have some operators << defined, but none is compatible with your type!".
Because sometimes it is not favourable to implement operators for your types (if you only output them once, e.g.), i suggested to write:
cout << sum.re << "--" << sum.im << endl; // or similar
This way, you write less code, and you are flexible in the output format. Who knows if you want you complex number formatted differently next time? But this is another discussion.
Why complicating that much? Because C++ can be awfully complicated. It it very powerfull, but crammed with special syntax and exceptions to those. In the end, the difference to C lies exactly here: C++ does a much better job with type inference (needed for templates), often resulting in WTF?
On how to implement it in your code, i think the other answers provide nice solutions!
sumit(a) returns an object of type Complex, which cout was not defined to handle.