C++ operator overload doesnt work - c++

I have a question about operators and how to overload them. There is an example of code and I'm overloading operator<< but it doesn't work. There is class that I use:
class CStudent{ //class for students and their attributes
int m_id;
int m_age;
float m_studyAverage;
public:
CStudent(int initId, int initAge, float initStudyAverage): m_id(initId), m_age(initAge), m_studyAverage(initStudyAverage){}
int changeId(int newId){
m_id = newId;
return m_id;
}
int increaseAge(){
m_age++;
return m_age;
}
float changeStudyAverage(float value){
m_studyAverage += value;
return m_studyAverage;
}
void printDetails(){
cout << m_id << endl;
cout << m_age << endl;
cout << m_studyAverage << endl;
}
friend ostream operator<< (ostream stream, const CStudent student);
};
Overload:
ostream operator<< (ostream stream, const CStudent student){
stream << student.m_id << endl;
stream << student.m_age << endl;
stream << student.m_studyAverage << endl;
return stream;
}
And there is main method:
int main(){
CStudent peter(1564212,20,1.1);
CStudent carl(154624,24,2.6);
cout << "Before the change" << endl;
peter.printDetails();
cout << carl;
peter.increaseAge();
peter.changeStudyAverage(0.3);
carl.changeId(221783);
carl.changeStudyAverage(-1.1);
cout << "After the change" << endl;
peter.printDetails();
cout << carl;
return 0;
}
Where is the problem?

The problem here is you need to learn what references are and the difference between std::ostream and std::ostream& is.
std::ostream& operator<< (std::ostream& stream, const CStudent& student)

Related

why is this code not detecting << operator?

Please explain to me why this is not detecting the << operator.
I tried my best, even tried to overload << on both classes (which is not necessary).
#include<iostream>
using namespace std;
const int MAX = 10;
class Complex;
template<class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return NULL;
}
else {
//return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) { real = r; imag = i; }
friend ostream& operator << (ostream& s, Complex& c);
};
ostream& operator << (ostream& s, Complex& c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
//cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
The function signature should be something like:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// write obj to stream
return os;
}
And the function pop can't return NULL since the type is not the same as t. Fixed code might like:
#include <iostream>
using namespace std;
const int MAX = 10;
class Complex;
template <class t>
class stack {
private:
t stk[MAX];
int top;
public:
stack() { top = -1; }
void push(t data) {
if (top == MAX - 1)
cout << "Stack is full.";
else
stk[++top] = data;
}
t pop() {
if (top == -1) {
cout << "Stack is empty.";
return {}; // May throw, or return std::optional here
} else {
// return stk[top--];
t data = stk[top];
top--;
return data;
}
}
};
class Complex {
private:
float real, imag;
public:
Complex(float r = 0.0, float i = 0.0) {
real = r;
imag = i;
}
friend ostream &operator<<(ostream &s, const Complex &c);
};
ostream &operator<<(ostream &s, const Complex &c) {
s << "(" << c.real << "," << c.imag << ")";
return s;
}
int main() {
stack<int> s1;
s1.push(10);
s1.push(20);
s1.push(30);
s1.push(40);
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
cout << s1.pop() << endl;
stack<float> s2;
s2.push(3.14f);
s2.push(4.14f);
s2.push(5.14f);
s2.push(6.14f);
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
cout << s2.pop() << endl;
Complex c1(1.5f, 2.5f), c2(1.5f, 2.5f), c3(1.5f, 2.5f), c4(1.5f, 2.5f);
// cout<<c1;
stack<Complex> s3;
s3.push(c1);
s3.push(c2);
s3.push(c3);
s3.push(c4);
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
cout << s3.pop() << endl;
return 0;
}
Online demo.
Related question: What are the basic rules and idioms for operator overloading?
It doesn't work because the second parameter should be a const reference
class Complex{
private:
float real,imag;
public:
Complex(float r=0.0,float i=0.0){
real=r;
imag=i;
}
friend ostream& operator<<(ostream& s, const Complex& c);
};
ostream& operator<<(ostream& s, const Complex& c) {
s<<"("<<c.real<<","<<c.imag<<")";
return s;
}
Reason:
The pop function returns an r-value. You can think of an r-value as a nameless object in memory (of course, there is more to it). You cannot put an r-value into an l-value reference. But for a const reference, it does not matter, since you are not going to modify it.
Solution 1:
friend ostream &operator<<(ostream &s, Complex &c); // accepts lvalue - c refers to some external Complex object.
friend ostream &operator<<(ostream &s, Complex &&c); // accepts rvalue - c becomes a normal local variable whose value is the passed rvalue.
Solution 2:
friend ostream &operator<<(ostream &s, const Complex &c); // accepts both

No match for operator << in exception handling program

#include <iostream>
#include <string>
#include "NegativeBalanceException.hpp"
#include <memory>
class Account
{
private:
std::string name;
double balance;
public:
Account(std::string name, double balance);
~Account() {std::cout <<"Calling Account Destroyer" << std::endl;}
void get_name() const {std::cout << name << std::endl;}
void get_balance() const {std::cout << balance << std::endl;}
friend std::ostream &operator<<(std::ostream &os, const Account &account);
};
Account::Account(std::string name, double balance)
: name{name}, balance{balance} {
if (balance < 0)
throw NegativeBalanceException();
}
std::ostream &operator<<(std::ostream &os, const Account &account) {
os << "Account Name: " << account.get_name() << "\n" << "Account
Balance: " << account.get_balance() << std::endl;
return os;
}
int main () {
std::unique_ptr<Account> Austin;
try {
Austin = std::make_unique<Account>("Austin",1000);
std::cout << *Austin << std::endl;
}
catch (const NegativeBalanceException &ex) {
std::cerr << ex.what() << std::endl;
}
};
Hello I am a beginner programmer and I am practicing exception handling and I do not know why my overloaded operator << is not working. It won't let me display my data that I want.
Your get_name() and get_balance() methods are both declared with void return values, so your overloaded operator<< can't pass them to os << .... Internally, the methods are doing their own logging to std::cout, so you would need to change your operator<< accordingly, eg:
std::ostream &operator<<(std::ostream &os, const Account &account) {
os << "Account Name: ";
account.get_name();
os << "Account Balance: ";
account.get_balance();
return os;
}
However, this will not work as expected if os does not refer to std::cout, for example if your main() decided to stream the Account to a std::ofstream instead.
A better option is to change get_name() and get_balance() to return values instead, and not do their own logging directly:
std::string get_name() const { return name; }
double get_balance() const { return balance; }
Then your overloaded operator<< will work as expected.
These
void get_name() const {std::cout << name << std::endl;}
void get_balance() const {std::cout << balance << std::endl;}
should be written like this
std::string get_name() const { return name; }
double get_balance() const { return balance; }
Functions which return values are not the same as functions which print values. In your overloaded operator<< you need two functions to return the values in the account object, so the operator<< can print them.

Adding Setters to a function template

I am trying to add setter to my project as a requirement but am stuck on making it work. I commented out the areas I have to add it but everything I have looked up has not worked. I know I am close but everything seems to not work.
#include "pch.h"
#include <string>
#include <conio.h>
#include <iostream>
using namespace std;
template <class T>
class Holder
{
private:
T thing;
int number; //add an integer data member that stores the number of data members of whatever class is stored in "thing"
public:
void standardInput();
void standardOutput();
void setNumber(int); // declare a setter function for the new data member
};
template <class T>
void Holder<T>::standardInput()
{
cout << endl;
cout << "You will be asked to enter " << n.setNumber << " items" << endl; // a line of output that use the data member with the number
cin >> Holder<T>::thing;
}
template <class T>
void Holder<T>::standardOutput()
{
cout << endl;
cout << "Here's the data you requested: " << endl;
cout << Holder<T>::thing << endl;
}
template<class T>
void Holder<T>::setNumber(int n) //implement the setter function for the new data member
{
setNumber = n;
}
// This is the first of two custom classes
class Student
{
friend ostream& operator<<(ostream&, Student&);
friend istream& operator>>(istream&, Student&);
private:
string name;
double tuiton;
};
ostream& operator<<(ostream& out, Student& a)
{
out << "The Student " << a.name << " Tuiton is: " << a.tuiton << endl;
return out;
}
istream& operator>>(istream& in, Student& a)
{
cout << "Enter the name of student: ";
in >> a.name;
cout << "What is the Price of tuiton? ";
in >> a.tuiton;
return in;
}
// This is the second of two custom classes
class FastFood
{
friend ostream& operator<<(ostream&, FastFood&);
friend istream& operator>>(istream&, FastFood&);
private:
int valueNumber;
double cost;
};
ostream& operator<<(ostream& out, FastFood& a)
{
out << " The Combo Number is " << a.valueNumber << " .It costs " << a.cost << endl;
return out;
}
istream& operator>>(istream& in, FastFood& a)
{
cout << "What is the Combo number? ";
in >> a.valueNumber;
cout << "Enter cost: ";
in >> a.cost;
return in;
}
int main()
{
cout << "For an integer: " << endl;
Holder<int> val;
// use the setter to store 1.
val.standardInput();
val.standardOutput();
cout << "For a Student:" << endl;
Holder<Student> aCollegeStudent;
// use the setter to store 2.
aCollegeStudent.standardInput();
aCollegeStudent.standardOutput();
Holder<FastFood> vMeal;
// use the setter to store 3.
vMeal.standardInput();
vMeal.standardOutput();
cout << endl;
system("pause");
return 0;
}
This is supposed to ask the integer along with the student and fastfood information. I required to add a setter in the template but wont need to use a getter due to standard input and output just cant figure out the right way to do it.

C++ compile error; stream operator overload

I'm learning C++ stream operator overloading. Can't get this to compile in Visual Studio.
In the istream& operator section, the compiler highlights the carats just after ins and says no operator >> matches these operands.
Can someone quick run it and tell me what's wrong?
*****************
// CoutCinOverload.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
class TestClass {
friend istream& operator >> (istream& ins, const TestClass& inObj);
friend ostream& operator << (ostream& outs, const TestClass& inObj);
public:
TestClass();
TestClass(int v1, int v2);
void showData();
void output(ostream& outs);
private:
int variable1;
int variable2;
};
int main()
{
TestClass obj1(1, 3), obj2 ;
cout << "Enter the two variables for obj2: " << endl;
cin >> obj2; // uses >> overload
cout << "obj1 values:" << endl;
obj1.showData();
obj1.output(cout);
cout << "obj1 from overloaded carats: " << obj1 << endl;
cout << "obj2 values:" << endl;
obj2.showData();
obj2.output(cout);
cout << "obj2 from overloaded carats: " << obj2 << endl;
char hold;
cin >> hold;
return 0;
}
TestClass::TestClass() : variable1(0), variable2(0)
{
}
TestClass::TestClass(int v1, int v2)
{
variable1 = v1;
variable2 = v2;
}
void TestClass::showData()
{
cout << "variable1 is " << variable1 << endl;
cout << "variable2 is " << variable2 << endl;
}
istream& operator >> (istream& ins, const TestClass& inObj)
{
ins >> inObj.variable1 >> inObj.variable2;
return ins;
}
ostream& operator << (ostream& outs, const TestClass& inObj)
{
outs << "var1=" << inObj.variable1 << " var2=" << inObj.variable2 << endl;
return outs;
}
void TestClass::output(ostream& outs)
{
outs << "var1 and var2 are " << variable1 << " " << variable2 << endl;
}
operator >>() should take TestClass& instead of const TestClass& as its 2nd parameter since you are expected to modify that parameter while reading from istream.
You should change the parameter type of inObj to reference to non-const, since it's supposed to be modified in operator>>. You can't modify on a const object, so you can't call opeartor>> on const object (and its members), that's what compiler complains.
friend istream& operator >> (istream& ins, TestClass& inObj);
Remove the qualifier const
friend istream& operator >> (istream& ins, const TestClass& inObj);
^^^^^
You may not change a constant object.

Overloading operator <<

class Vehicle
{
public:
//[...]
virtual std::ostream& ostreamOutput(std::ostream&) const; // virtual in order to use it for subclasse like cars, busses etc.
virtual double Speed() const; //returns the speed of a vehicle, is implemented in derived classes
private:
int Number
std::string Name
//[...]
protected:
int MaxSpeed; //these variables were also needed in the derived classes
};
std::ostream& Vehicle::ostreamOutput(std::ostream& os) const
{
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed
return os;
}
std::ostream& operator<<(std::ostream& os, const Vehicle& x)
{
x.ostreamOutput(os);
return os;
}
main() //I wanted to overload the "<<"-Operator in order to print the vehicle information without //a seperate function
{
Vehicle Vehicle1("Vehicle1", 80);
std::cout << Vehicle1 << std::endl;//the first shift-operator contains the error
}
I tried to overload the Shiftoperator but I get the error named:
"error c2679 binary ' ' no operator found which takes a right-hand operand of type".
The error occured in the first Shift Operator in the main function. I want to print Vehicle and its derived classes with the overloaded operator.
Can you explain the error to me? I really do not know how to correct this.
I fixed all the typos (missed semicolons) in your source, and here is a complete working example:
#include <iostream>
#include <iomanip>
using namespace std;
class Vehicle
{
public:
//[...]
Vehicle (const char* Name, int Number)
: Name (Name), Number (Number)
{}
virtual std::ostream& ostreamOutput(std::ostream&) const; // virtual in order to use it for subclasse like cars, busses etc.
virtual double Speed() const {return 0.;} //returns the speed of a vehicle, is implemented in derived classes
private:
// remove in-class initializers below if you need to avoid C++11
int Number = -1;
std::string Name = "not set";
//[...]
protected:
int MaxSpeed = 200; //these variables were also needed in the derived classes
};
std::ostream& Vehicle::ostreamOutput(std::ostream& os) const
{
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed;
return os;
}
std::ostream& operator<<(std::ostream& os, const Vehicle& x)
{
x.ostreamOutput(os);
return os;
}
int main() //I wanted to overload the "<<"-Operator in order to print the vehicle information without //a seperate function
{
Vehicle Vehicle1("Vehicle1", 80);
std::cout << Vehicle1 << std::endl;//the first shift-operator contains the error
}
Maybe you output some other variables for which operator<< is not defined. To debug this case, split the code from e.g. this:
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed;
to this:
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number;
os << std::setw(9) << Name;
os << std::setw(15) << Speed();
os << std::setw(5) << MaxSpeed;
This way you'll get the error message for the real line that is causing trouble. Otherwise you'll get the error message only for the first line, the compiler you use apparently does not distinguish the lines in this case.
Your code example contains only typos (Vehicle <-> Fahrzeug, ostreamAusgabe <-> ostreamOutput, semicolon after Speed() in ostreamOutput()). Overloaded operator<< should work fine.
Try to compile and launch this code:
class Vehicle
{
public:
Vehicle(const std::string& name, int num)
: Name(Name)
, Number(num)
, MaxSpeed(100)
{}
virtual std::ostream& ostreamOutput(std::ostream&) const;
virtual double Speed() const;
private:
int Number;
std::string Name;
protected:
int MaxSpeed;
};
double Vehicle::Speed() const
{
return 0.0;
}
std::ostream& Vehicle::ostreamOutput(std::ostream& os) const
{
os << std::resetiosflags(std::ios::right) << std::setiosflags(std::ios::left) << std::setfill(' ') << ""
<< std::setw(4) << Number
<< std::setw(9) << Name
<< std::setw(15) << Speed()
<< std::setw(5) << MaxSpeed;
return os;
}
std::ostream& operator<<(std::ostream& os, const Vehicle& x)
{
x.ostreamOutput(os);
return os;
}
int main()
{
Vehicle Vehicle1("Vehicle1", 80);
std::cout << Vehicle1 << std::endl;
return 0;
}