C++: Issue overloading I/O operators - c++

I'm currently finding it impossible to fix an occurrence of infinite recursion in my code.
I have the following header that defines the Proces class:
#pragma once
#include <iostream>
class Proces {
std::string name;
int maxWaitTime;
int timeToFinish;
int timeWaited;
int timeProcessed;
public:
Proces(std::string n, int mwt = 1, int ttf = 1) :name(n), maxWaitTime(mwt), timeToFinish(ttf), timeWaited(0), timeProcessed(0) {}
bool process(int a = 1) { timeProcessed += a; return isComplete(); }
bool isComplete() { return timeProcessed >= timeToFinish; }
bool wait(int a = 1) { timeWaited += a;return maxWaitReached(); }
bool maxWaitReached() { return maxWaitTime <= timeWaited; }
friend bool operator<(const Proces& a, const Proces& b);
friend bool operator>(const Proces& a, const Proces& b);
friend std::ostream &operator<<(std::ostream &output, const Proces& a);
friend std::istream &operator>>(std::istream &input, const Proces& a);
};
Then, for the implementation of the operators, I have:
#include "proces.h"
bool operator<(const Proces & a, const Proces & b)
{
if (a.timeWaited != b.timeWaited)
return a.timeWaited < b.timeWaited;
else
return a.maxWaitTime < b.maxWaitTime;
}
bool operator>(const Proces & a, const Proces & b)
{
return ! (a < b);
}
std::ostream & operator<<(std::ostream & output, const Proces & a)
{
output << a.naziv << " MWT:" << a.maxWaitTime << " TTC:" << a.timeToFinish << " WT:" << a.timeWaited << " TP:" << a.timeProcessed;
return output;
}
std::istream & operator>>(std::istream & input,Proces & a)
{
input >> a.name >> a.maxWaitTime >> a.timeToFinish;
a.timeWaited = 0;
a.timeProcessed = 0;
return input;
}
This lead to two (as far as I know unrelated) problems:
Use of the output operator lead to said infinite recursion happening
The code itself cannot be compiled without commenting out the implementation
of the input operator as it claims the fields of the class are inaccessible
in spite of being a friend of the class
Severity Code Description Project File Line Suppression State
Error (active) E0265 member "Proces::name" (declared at line 4 of "[project path]\proces.h") is inaccessible aspdz2 [project path]\proces.cpp
Here is the main function (the < and > operators work as intended):
#include "proces.h"
int main() {
Proces a{ "Glorious prces",1,2 };
Proces b{ "Glorious prces2",2,2 };
if (a < b)std::cout << "A is lesser" << std::endl;
else std::cout << "B is lesser" << std::endl;
if (a > b)std::cout << "A is greater" << std::endl;
else std::cout << "B is greater" << std::endl;
b.wait(-1);
if (a < b)std::cout << "A is lesser" << std::endl;
else std::cout << "B is lesser" << std::endl;
//Infinite recursion happens here:
std::cout << b << std::endl;
}

It appears that the reason for the
Severity Code Description Project File Line Suppression State Error (active) E0265 member "Proces::name" (declared at line 4 of "[project path]\proces.h") is inaccessible aspdz2 [project path]\proces.cpp
error was due to the accidental inclusion of the const keyword in the declaration of the >> operator;
The recursion on the other hand was happening because I forgot to#include<string>

Related

Reading from file writing to class member functions and printing on console in C++?

I have 2 classes, I make an object from the second class (I pass the filename as an argument). It should print the contents of the file which contains the following data in the following format:
A.Yordanov 1234567819
S.Todorov 3456789120
D.Lazarov 2569789054
P.Pavlov 4329549823
M.Kalinova 2367892343
B.Georgiev 659045324
I have overloaded the << operator but I when I try to cout << cty2 nothing appears on the console even though I have put the file in the same directory?
// OOP_Homework.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <fstream>
#include <set>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
fstream f;
class CPerson {
string name;
string egn;
public:
CPerson(string n, string e) {
name = n;
egn = e;
}
friend bool operator<(CPerson p1, CPerson p2) {
if (p1.egn < p2.egn) {
return true;
}
return false;
}
friend bool operator==(CPerson p1, CPerson p2) {
if (p1.egn == p2.egn) {
return true;
}
return false;
}
friend ostream& operator<< (ostream o, CPerson pn) {
o << "Egn" << endl;
o << pn.egn << endl;
o << "Name:" << endl;
o << pn.name << endl;
}
friend istream& operator>> (istream is, CPerson p) {
is >> p.egn;
is >> p.name;
return is;
}
string getName() {
return name;
}
string getEgn() {
return egn;
}
void setName(string n) {
name = n;
}
void setEgn(string e) {
egn = e;
}
};
class CCity {
vector<CPerson> pr;
public:
CCity(string fl) {
f.open(fl, ios::out);
string name = "", fn = "";
while (!f.eof()) {
//формата на данните във файла е във вида:
//<име на студент> <факултетен номер>
cin >> name >> fn;
pr.push_back(CPerson(name, fn));
}
f.close();
}
//помощен getter за вектора pr;
vector<CPerson> getV() {
return pr;
}
friend ostream& operator<<(ostream& os, CCity& psn) {
vector<CPerson> ps = psn.getV();
for (auto x = ps.begin(); x != ps.end(); x++) {
os << x->getName() << endl;
os << x->getEgn() << endl;
}
return os;
}
vector<CPerson> getDuplicate() {
set<CPerson> temp;
vector<CPerson> duplicates;
for (auto i = pr.begin(); i != pr.end(); i++) {
for (auto x : pr) {
if (*i == x) {
temp.insert(*i);
}
}
}
for (auto j : temp) {
duplicates.push_back(j);
}
temp.clear();
//връщаме студентите с повтарящи се егн-та
return duplicates;
}
void removeDuplicates() {
sort(pr.begin(),pr.end());
pr.erase(unique(pr.begin(), pr.end()));
}
void removeVector(vector<CPerson> ob) {
for (auto i:ob) {
for (auto x = pr.begin(); x != pr.end(); x++) {
if (i == *x) {
pr.erase(x);
}
}
}
}
};
int main()
{
CCity cty2("persons.txt");
//cout << cty1 << endl;
cout << cty2 << endl;
return 0;
}
The code for your overload for operator<< should be
friend ostream& operator<< (ostream &o, const CPerson &pn) {
// ^ ^^^^^ ^
o << "Egn" << endl;
o << pn.egn << endl;
o << "Name:" << endl;
o << pn.name << endl;
return o; // since return type is ostream&
}
You should be passing the stream by reference and returning it once you've finished using it. Passing by-reference ensures that the same stream is used (unlike pass-by-value).
Another thing to note would be your CPerson p function arguments. These should be passed by-reference as well. With operator<<, your CPerson won't be modified, so we can keep it as const.
You may also want to watch out your operator>>. Again, istream is should be istream &is. With the CPerson p parameter, you will modify it, so you'll definitely want to be passing it as a reference.
friend istream& operator>> (istream &is, CPerson &p) {
// ^ ^
is >> p.egn;
is >> p.name;
return is;
}
In your other overloads, you should be using const CPerson &p as well. Moreover, your overloads for operator< and operator== don't need to be friended since they're not accessing any other class's private members. Thus,
bool operator<(const CPerson &p1, const CPerson &p2) {
if (p1.egn < p2.egn) {
return true;
}
return false;
}
bool operator==(const CPerson &p1, const CPerson &p2) {
if (p1.egn == p2.egn) {
return true;
}
return false;
}
You'll want to get used to passing your classes by-reference as it saves space (not having to copy-construct another instance of the class as passing by-value would do). It's thus, more efficient both space-wise and performance-wise to pass your classes by reference.

C++ Operator overloading for << with abstract class

Here are my header files:
//Frame.h
#pragma once
class Frame {
string frameName;
protected:
double fileSize;
vector<Attribute> attributes;
public:
Frame(string f, double size, vector<Attribute> d) :frameName(f), fileSize(size), attributes(d) {}
virtual ~Frame() {}
string& GetFrameName() { return frameName; }
Attribute& operator[](int);
int size() { return attributes.size(); }
virtual void Compress() = 0;
friend ostream& operator<<(ostream&, Frame&);
};
// AudioFrame
#pragma once
class AudioFrame :public Frame {
static const int RATES = 3;
static constexpr double BITRATE[]{128,160,192};
static constexpr double COMPRESSION_RATIO[]{11.1,9.1,7.1};
public:
AudioFrame(string frameName, double fileSize, vector<Attribute> d) :Frame(frameName,fileSize, d) {}
~AudioFrame(){}
void Compress();
friend ostream& operator<<(ostream&, AudioFrame&);
};
//ImageFrame.h
#pragma once
class ImageFrame :public Frame {
static const int BITS = 8;
static constexpr double COMPRESSION_RATIO = 6.0;
static constexpr double BITDEPTH_FACTOR[] {11.1,4.6,3.5,2.4,1.9,1.5,1.2,1.0};
public:
ImageFrame(string fileName, double fileSize, vector<Attribute> d) :Frame(fileName, fileSize, d) {}
~ImageFrame(){}
void Compress();
friend ostream& operator<<(ostream&, ImageFrame&);
};
Each one of them have a **friend ostream& operator<<(ostream&, ImageFrame&);**
But when i do this
ImageFrame test;
cout << test << endl;
Only Frame class's operator << is called. Any solution to this?
Also, professor doesn't want me to change anything from the header files!
EDIT:
here is how i implement the operator <<:
// code from AudioFrame.cpp
ostream& operator<<(ostream& os, AudioFrame& obj) {
os << "AudioFrame" << endl;
os << "Name = " << obj.GetFrameName() << endl;
for (unsigned int i = 0; i < obj.attributes.size(); i++) {
os << "\tBandwidth #" << i << ": " << obj.attributes[i] << endl;
}
return os;
}
// code from ImageFrame.cpp
ostream& operator<<(ostream& os, ImageFrame& obj) {
os << "ImageFrame" << endl;
os << "Name = " << obj.GetFrameName() << endl;
for (unsigned int i = 0; i < obj.attributes.size(); i++) {
os << "\tResolution #" << i << ": " << obj.attributes[i] << endl;
}
return os;
}
// code from Frame.cpp
ostream& operator<<(ostream& os, Frame& obj) {
return os;
}
But when i run the test code, only the code from Frame.cpp is run.
EDIT2:
So i feel like i should also share my real test code:
int type;
deque<Frame*> frames; // all frames are stored here
// user is promoted a console menu for selecting a frame type (ImageFrame or AudioFrame)
if (type == 1)
frames.push_back(new AudioFrame(...));
else
frames.push_back(new ImageFrame(...));
// now when i need to print all frames i do
for (unsigned int i = 0; i < frames.size(); i++)
cout << *(frames[i]) << endl;
If you REALLY want cout << *(frames[i]) << endl; to dispatch polymorphically, and you REALLY cannot alter the headers, then you have no choice but to rely on dynamic typing.
ostream& operator<<(ostream& stream, Frame& frame) {
AudioFrame* as_audio_frame = dynamic_cast<AudioFrame*>(&frame);
ImageFrame* as_image_frame = dynamic_cast<ImageFrame*>(&frame);
if(as_audio_frame) {
return stream << *as_audio_frame;
}
if(as_image_frame) {
return stream << *as_image_frame;
}
//normal frame code
}
However, this is TERRIBLE code, and signals that some reorganizing is severely needed in the headers. So i suspect there is something wrong in your intrepretation of your assignment.
Edit, well, actually, there is a hilariously overengineered alternative...
class FrameAdapterInterface {
public:
virtual ~FrameAdapterInterface() {};
protected:
virtual std::ostream print(std::ostream&) = 0;
friend ostream& operator<<(ostream&, FrameAdapterInterface &);
};
template<typename FRAME_T>
class AdapatedFrameType : public FrameAdapterInterface {
FRAME_T data_;
public:
template<typename... ARGS_T>
AdapatedFrameType(ARGS_T&&... args)
: data_(std::forward<ARGS_T>(args)...) {}
ostream& print(std::ostream& stream) override {
return stream << data_;
}
};
ostream& FrameAdapterInterface::operator<<(ostream& stream, FrameAdapterInterface& frame) {
return frame.print(stream);
}

debugging error at the end of the console

I'm a student and I studying c++.
This is my cpp code
int _tmain(int argc, _TCHAR* argv[])
{
CFood output;
output.whatFunc();
cout<<"my outputs"<<endl<<output<<endl;
return 0;
}
ostream& operator <<(ostream& outputStream, const CFood& output)
{
for(int i=0; i<2; i++)
{
outputStream <<"1 : "<<output.m_strName[i]<<" 2 : "<<output.m_servingSize[i]<<"g "<<"3 : "<<
output.m_calorie[i]<<"cal "<<"4 : "<<output.m_transFat[i]<<"g"<<endl;
}
return outputStream;
}
When I debug it, It work. But the end of the console, it gives me error message;;;
It says "An unhandled win32 exception occurred in work.exe [5796]"
My header filed is
class CFood
{
public:
CFood(void);
~CFood(void);
private:
string m_strName[7];
double m_servingSize[7];
double m_calorie[7];
double m_transFat[7];
public:
void whatFunc(void);
friend ostream& operator <<(ostream& outputStream,const CFood& output);
}
I think there is something wrong in my code..And I think it's CFood output;(Just thinking..)
Do you know why it has debug error?
++Sorry, I forgot the whatFunc(void)
This is code
void CFood::whatFunc(void) //
{
m_strName[0]="chicken";
m_strName[1]="rice";
m_strName[2]="meat";
m_strName[3]="strawberry";
m_strName[4]="apple";
m_strName[5]="water";
m_strName[6]="juice";
m_servingSize[0]=10;
m_servingSize[1]=20;
m_servingSize[2]=30;
m_servingSize[3]=40;
m_servingSize[4]=50;
m_servingSize[5]=60;
m_servingSize[6]=70;
m_calorie[0]=10.45;
m_calorie[1]=20.57;
m_calorie[2]=30.78;
m_calorie[3]=40.23;
m_calorie[4]=50.85;
m_calorie[5]=60.73;
m_calorie[6]=70.27;
m_transFat[0]=0.01;
m_transFat[1]=0.02;
m_transFat[2]=0.03;
m_transFat[3]=0.04;
m_transFat[4]=0.05;
m_transFat[5]=0.06;
m_transFat[6]=0.07;
}
Well its difficult to tell what exactly goes wrong without full source code. In my humble opinion, entire source lefts much to be desired. Placing obviously linked data in the bunch of the unlinked arrays with static size is not a very good pattern. Instead try something like that:
#include <iostream>
#include <vector>
#include <string>
#include <ostream>
struct CFoodItem{
std::string m_strName;
double m_servingSize;
double m_calorie;
double m_transFat;
};
class CFood
{
public:
void AddFoodItem(const CFoodItem& cItem);
friend std::ostream& operator <<(std::ostream& outputStream, const CFood& output);
private:
std::vector<CFoodItem> m_vItems;
};
std::ostream& operator <<(std::ostream& outputStream, const CFood& output)
{
for (auto i = output.m_vItems.begin(); i != output.m_vItems.end(); ++i)
{
outputStream << "1 : " << i->m_strName << " 2 : " << i->m_servingSize << "g " << "3 : " <<
i->m_calorie << "cal " << "4 : " << i->m_transFat << "g" << std::endl;
}
return (outputStream);
}
void CFood::AddFoodItem(const CFoodItem& cItem)
{
m_vItems.push_back(cItem);
}
int __cdecl main(void)
{
CFood output;
CFoodItem itm;
itm.m_strName = "some food";
itm.m_servingSize = 100500;
itm.m_calorie = 42;
itm.m_transFat = 42;
output.AddFoodItem(itm);
std::cout << "my outputs" << std::endl << output << std::endl;
return 0;
}

No operator << matches these operands [duplicate]

This question already has answers here:
How can I use cout << myclass
(5 answers)
Closed 4 months ago.
I've been reading questions here for an hour or two regarding this error I'm getting and most of them forgot to #include string (which I had already done), or to overload the << operator.
Here's the code in question:
void Student::getCoursesEnrolled(const vector<Course>& c)
{
for (int i = 0; i < c.size(); i++)
{
cout << c[i] << endl;
}
}
And the error I'm getting:
Error: No operator matches these operands
operand types are: std::ostream << const Course
All I'm trying to do is return the vector. I read about overloading the << operator but we haven't learned any of that in class so I'm assuming there is another way of doing it?
I appreciate your time!
All I'm trying to do is return the vector.
Not quite; you're trying to print it using cout. And cout has no idea how to print a Course object, unless you provide an overloaded operator<< to tell it how to do so:
std::ostream& operator<<(std::ostream& out, const Course& course)
{
out << course.getName(); // for example
return out;
}
See the operator overloading bible here on StackOverflow for more information.
The problem is that operator << is not overload for type Course objects of which you are trying to output in statement
cout << c[i] << endl;
You need to overload this operator or write your own function that will output an object of type Course in std::ostream
For example let assume that below is a definition of class Course
class Course
{
private:
std::string name;
unsigned int duration;
public:
Course() : duration( 0 ) {}
Course( const std::string &s, unsigned int n ) : name( s ), duration( n ) {}
std::ostream & out( std::ostream &os ) const
{
return ( os << "Course name = " << name << ", course duration = " << duration );
}
};
When you can write
std::vector<Course> v = { { "A", 1 }, { "B", 2 }, { "C", 3 } };
for ( const Course &c : v ) c.out( std::cout ) << std::endl;
Instead member function out you can overload operator <<. For example
class Course
{
private:
std::string name;
unsigned int duration;
public:
Course() : duration( 0 ) {}
Course( const std::string &s, unsigned int n ) : name( s ), duration( n ) {}
friend std::ostream & operator <<( std::ostream &os, const Course & c )
{
return ( os << "Course name = " << c.name << ", course duration = " << c.duration );
}
};
and use it as
std::vector<Course> v = { { "A", 1 }, { "B", 2 }, { "C", 3 } };
for ( const Course &c : v ) std::cout << c << std::endl;
The stream operator << is used to "output" some representation of that object. If you don't want to overload the operator yet just pick some property to output instead:
for (int i = 0; i < c.size(); i++)
{
cout << c[i].Name << endl; // assuming Name is a property of Course
}
When you DO overload the operator you just decide then what the proper representation of a Course is:
ostream& operator<< (ostream &out, Course &c)
{
out << c.Name "(" << c.Description << ")";
return out;
}
Your Course class needs to implement an operator:
class Course
{
public:
/*
* Your code here
*/
// Probably missing this:
friend std::ostream& operator << (std::ostream& os, const Course& course)
{
os << course.name(); // etc..
return os;
};
}; // eo class Course
Since you haven't yet learned to overload operator<<, what you can do instead is to print each member of your Course class. You haven't posted the definition of Course, but perhaps it's something like this:
class Course
{
public:
int get_number() { return _number; }
const std::string& get_name() { return _name; }
private:
int _number;
std::string _name;
};
then you can say:
void Student::getCoursesEnrolled(const vector<Course>& c)
{
for (int i = 0; i < c.size(); i++)
{
cout << c[i].get_number() << " "
<< c[i].get_name() << std::endl;
}
}
Your problem is this particular part:
cout << c[i]
In your case c[i] is an object of type Course as dvnrrs correctly pointed out. So either:
implement the overloaded << operator for your object OR
if your Course object is in someway a typedef to a primitive try explicitly casting it to a string type (or similar)

C++ - ostream, friends and namespaces

Everything was fine until I moved my objects to a namespace. And now the compiler claims that my Color attributes are private.
I thought the whole point of friends was to share encapsulated information with those a class befriends.
Color.h
friend ostream & operator << (ostream& output, const st::Color& color);
Color.cpp:
ostream & operator <<(ostream& output, const st::Color& color) {
output << "Colors:\nalpha\t: " << color.a << "\nred\t: " << color.r << "\ngreen\t: " << color.g
<< "\nblue\t: " << color.b << "\nvalue\t: " << color.color();
return output;
}
error:
Color.h||In function 'std::ostream& operator<<(std::ostream&, const st::Color&)':|
Color.h|52|error: 'unsigned char st::Color::a' is private|
Color.cpp|15|error: within this context|
Color.h|49|error: 'unsigned char st::Color::r' is private|
Color.cpp|15|error: within this context|
Color.h|51|error: 'unsigned char st::Color::g' is private|
Color.cpp|15|error: within this context|
Color.h|50|error: 'unsigned char st::Color::b' is private|
Color.cpp|16|error: within this context|
||=== Build finished: 8 errors, 0 warnings (0 minutes, 1 seconds) ===|
So what is the deal?
I'm using Code::Blocks as my IDE. And it won't even show any properties or methods when I use the dot operator on the "color" parameter. This is obviously a sign of something going wrong...somewhere.
I've taken the friend operator overloading out and it compiles just fine. No error elsewhere.
What gives?
It's declared as follows:
namespace st{
class Color {
friend ostream & operator << (ostream& output, const st::Color& color);
public:
....
private:
.....
};
};
Edit:
In my CPP I've now done this:
namespace st{
ostream & st::operator <<(ostream& output, const st::Color& color) {
output << "Colors:\nalpha\t: " << color.a << "\nred\t: " << color.r << "\ngreen\t: " << color.g
<< "\nblue\t: " << color.b << "\nvalue\t: " << color.color();
return output;
}
}
st::Color::Color() {
reset();
}
st::Color::Color(const Color& orig) {
a = orig.a;
r = orig.r;
g = orig.g;
b = orig.b;
}
void st::Color::reset() {
a = 0;
r = 0;
g = 0;
b = 0;
}
... etc
}
No compile errors, but is it normal for such a situation to use the namespace again in the header? Or is this completely off from what I should be doing?
Edit:
#Rob thanks for your input as well!
You need to declare and define your operators in the same namespace as the object as well. They will still be found through Argument-Dependent-Lookup.
A usual implementation will look like this:
/// header file
namespace foo {
class A
{
public:
A();
private:
int x_;
friend std::ostream& operator<<(std::ostream& o, const A& a);
};
std::ostream& operator<<(std::ostream& o, const A& a);
} // foo
// cpp file
namespace foo {
A::A() : x_(23) {}
std::ostream& operator<<(std::ostream& o, const A& a){
return o << "A: " << a.x_;
}
} // foo
int main()
{
foo::A a;
std::cout << a << std::endl;
return 0;
}
Edit
It seems that you are not declarin your operator<< in the namespace and are also defining it outside of the namespace. I've adjusted the code.
You need to qualify your operator with the namespace as well. It is a function signature declared in the name space so to access its symbol you need to prefix it with the namespace.
Try it like this:
namespace st {
ostream & operator <<(ostream& output, const Color & color) {
output << "Colors:\nalpha\t: " << color.a
<< "\nred\t: " << color.r
<< "\ngreen\t: " << color.g
<< "\nblue\t: " << color.b
<< "\nvalue\t: " << color.color();
return output;
}
}