#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.
Related
I was trying to learn operator overloading in C++ PL. I made an exercise shown below. What I want to do is overload << operator for each derived class and use it on my main. But whenever I do it, its only working for Base class. What is the problem here?
Class Employee:
class Employee {
public:
string name;
int id;
int exp_level;
double salary;
Employee() {
this->name = "";
this->id = 0;
this->exp_level = 0;
this->salary = 0.0;
}
~Employee() {
//WTF
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Employee& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << endl;
return os;
}
};
Class Technical:
class Technical : public Employee {
public:
string profession;
Technical() {
this->profession = "";
}
~Technical() {
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Technical& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << "Technical" << endl;
return os;
}
};
Class Engineer:
class Engineer : public Employee {
public:
Engineer() {
}
~Engineer() {
}
virtual void calculateSalary() {
//CODE
}
virtual void registerX() {
//CODE
}
friend ostream& operator<<(ostream& os, const Engineer& e) {
os << e.name << " " << e.exp_level << " " << e.id << " " << e.salary << "Engineer" << endl;
return os;
}
};
Main Method:
int main()
{
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
cout << *e << endl;
cout << *t << endl;
cout << *ee << endl;
}
Output:
0 0 0
0 0 0
0 0 0
C++ chooses the best overload based on the static type's of the function arguments, and because the type is Employee in this case, the Employee's operator<< gets called.
If you want it to call the correct version when you have a static type pointer / reference to it that doesn't match it's dynamic type you'll have to use a virtual function or use dynamic_casts / typeid to check for the concrete runtime type (virtual functions are the cleanest approach imho)
Example: godbolt
class Employee {
public:
virtual ~Employee() = default;
friend std::ostream& operator<<(std::ostream& os, const Employee& e) {
return e.put(os);
}
protected:
virtual std::ostream& put(std::ostream& os) const {
os << "Employee!";
return os;
}
};
class Technical : public Employee {
protected:
std::ostream& put(std::ostream& os) const override {
os << "Technical Employee!";
return os;
}
};
class Engineer : public Employee {
protected:
std::ostream& put(std::ostream& os) const override {
os << "Engineer Employee!";
return os;
}
};
int main() {
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
std::cout << *e << std::endl;
std::cout << *t << std::endl;
std::cout << *ee << std::endl;
delete ee;
delete t;
delete e;
}
would result in:
Employee!
Technical Employee!
Engineer Employee!
Also keep in mind that once you have at least 1 virtual function in a class then the destructor should almost definitely be also virtual.
e.g.:
Employee* e = new Technical();
delete e;
would only call ~Employee(), but not ~Technical(), if the destructor is not virtual.
So whenever you want to delete an object through a pointer to one of it's base-classes the destructor needs to be virtual, otherwise it's undefined behavior.
Due to these declarations
Employee* e = new Employee();
Employee* t = new Technical();
Employee* ee = new Engineer();
the static type of the expressions *e, *t, *ee is Employee &. So the operator
friend ostream& operator<<(ostream& os, const Employee& e)
is called for all three objects.
A simple way to make the friend operator << "virtual" is to define in each class a virtual function like for example
virtual std::ostream & out( std::ostream & ) const;
and define the (only) friend operator like
friend ostream& operator<<(ostream& os, const Employee& e)
{
return e.out( os );
}
The virtual function out need to be redefined in each derived class.
Is there a way to create a function which you can use between two << operators in an ostream?
Let's assume the function's name is usd, and might look something like:
std::ostream& usd(std::ostream& os, int value) {
os << "$" << value << " USD";
return os;
}
Then I would like to use it like:
int a = 5;
std::cout << "You have: " << usd(a) << std::endl;
Which would print:
You have: $5 USD
I would prefer a solution without the need for a class.
If you must use a class I would prefer not to mention the class at all when using the usd function. (For example how the std::setw function works)
EDIT:
In my implementation I intend to use the std::hex function, the one described above was just a simplified example but probably shouldn't have.
std::ostream& hex(std::ostream& os, int value) {
os << "Hex: " << std::hex << value;
return os;
}
So I am not sure if a function returning a simple string is sufficient.
To obtain the usage you described:
int a = 5;
std::cout << "You have: " << usd(a) << std::endl;
You'd simply need usd(a) to return something that you have an ostream<< operator for, like a std::string, and no custom ostream<< operator is needed.
For example:
std::string usd(int amount)
{
return "$" + std::to_string(amount) + " USD";
}
You can write other functions to print in other currencies, or to convert between them, etc but if all you want to handle is USD, this would be sufficient.
If you used a class representing money, you could write an ostream<< for that class and you wouldn't need to call a function at all (given that your default ostream<< prints USD)
class Money
{
int amount;
};
std::ostream& usd(std::ostream& os, Money value) {
os << "$" << value.amount << " USD";
return os;
}
int main(int argc, char** argv)
{
Money a{5};
std::cout << "You have: " << a << std::endl; // Prints "You have: $5 USD"
return 0;
}
I don't know how to do this without a class. However, it is easy to do with a class.
struct usd {
int value;
constexpr usd(int val) noexcept : value(val) {}
};
std::ostream& operator<<(std::ostream& os, usd value) {
os << "$" << value.value << " USD";
return os;
}
for hex
struct hex {
int value;
constexpr hex(int val) noexcept : value(val) {}
};
std::ostream& operator<<(std::ostream& os, hex value) {
os << "Hex: " << std::hex << value.value;
return os;
}
usage
int a = 5;
std::cout << "You have: " << usd(a) << std::endl;
std::cout << "You have: " << hex(a) << std::endl;
So, I have a struct Bike, which looks like this
struct Bike {
std::string brand;
std::string model;
bool is_reserved;
friend std::ostream& operator<<(std::ostream out, const Bike& b);
};
std::ostream& operator<<(std::ostream out, const Bike& b) {
return out
<< "| Brand: " << b.brand << '\n'
<< "| Model: " << b.model << '\n';
}
And another class BikeRentalService, which has a std::vector<Bike*> called bikes_m. This class also has a method print_available_bikes(), which is supposed to iterate over said std::vector<Bike*> and print each Bike by using the overloaded operator<< shown above. This method looks like that:
void BikeRentalService::print_available_bikes(std::ostream& out) {
if (bikes_m.empty()) {
out << "| None" << '\n';
}
else {
for (auto bike : bikes_m) {
if (!bike->is_reserved) {
out << bike;
}
}
}
}
The problem is that using this function just prints out the addresses of those Bike objects. Dereferencing the objects before using out << does not work either, Visual Studio says it can't reference std::basic_ostream because it is a "deleted function".
Writing the for loop as (auto *bike : bikes_m) does not change anything.
The rigth way to overload the ostream operator is as follows:
struct Bike {
std::string brand;
std::string model;
bool is_reserved;
friend std::ostream& operator<<(std::ostream& out, const Bike& b); // <- note passing out by reference
};
std::ostream& operator<<(std::ostream& out, const Bike& b) {
return out
<< "| Brand: " << b.brand << '\n'
<< "| Model: " << b.model << '\n';
}
Also, as noted by #KyleKnoepfel you should change out << bike; to out << *bike; too.
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;
}
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)