Virtual overloaded operators >> and << - c++

I need an interface that would require its subclasses to overload << and >>, but I'm not quite sure how since these operators aren't overloaded as member functions:
std::istream& operator>> (std::istream& in, Student& student) {
in >> student.name >> student.group;
for (int& i : student.marks) { in >> i; }
return in;
}
Maybe there's a way to make it a member function?

You could do something like this:
class StudentInterface
{
public:
virtual void readSelfFrom(std::istream& in) = 0;
};
std::istream& operator>> (std::istream& in, StudentInteface& student)
{
student.readSelfFrom(in);
return in;
}
And then let users derive from StudentInterface, eg:
class Student: public StudentInterface
{
public:
void readSelfFrom(std::istream& in) override
{
in >> name >> group;
for (int& i : marks) { in >> i; }
}
};

A general approach in such a case is to declare in the base class a virtual member function like
virtual std::ostream & out( std::ostream &os = std::cout ) const;
In derived classes the function will be overriden.
Then the operator << can look like
std::ostream & operator <<( std::ostream &os, const Base &obj )
{
return obj.out( os );
}
A similar way can be defined the operator >> only in this case the virtual member function will not be constant..

Related

How does cin read strings into an object of string class?

Reading some documentation online I found that istream class was part of C++ long before the string class was added. So the istream design recognizes basic C++ types such as double and int, but it is ignorant of the string type. Therefore, there are istream class methods for processing double and int and other basic types, but there are no istream class methods for processing string objects.
My question is if there are no istream class methods for processing string objects, why this program works and how ?
#include <iostream>
int main(void)
{
std::string str;
std::cin >> str;
std::cout << str << std::endl;
return 0;
}
This is possible with the use operator overloading. As shown in the below example, you can create your own class and overload operator>> and operator<<.
#include <iostream>
class Number
{
//overload operator<< so that we can use std::cout<<
friend std::ostream& operator<<(std::ostream &os, const Number& num);
//overload operator>> so that we can use std::cin>>
friend std::istream &operator>>(std::istream &is, Number &obj);
int m_value = 0;
public:
Number(int value = 0);
};
Number::Number(int value): m_value(value)
{
}
std::ostream& operator<<(std::ostream &os, const Number& num)
{
os << num.m_value;
return os;
}
std::istream &operator>>(std::istream &is, Number &obj)
{
is >> obj.m_value;
if (is) // check that the inputs succeeded
{
;//do something
}
else
{
obj = Number(); // input failed: give the object the default state
}
return is;
}
int main()
{
Number a{ 10 };
std::cout << a << std::endl; //this will print 10
std::cin >> a; //this will take input from user
std::cout << a << std::endl; //this will print whatever number (m_value) the user entered above
return 0;
}
By overloading operator>> and operator<<, this allows us to write std::cin >> a and std::cout << a in the above program.
Similar to the Number class shown above, the std::string class also makes use of operator overloading. In particular, std::string overloads operator>> and operator<<, allowing us to write std::cin >> str and std::cout << str, as you did in your example.
Because std::string overload the >> and << operator to return the type std::istream and std::ostream
How they overload it, you can look in this link that Mat gives.
You can create your own class and overload operators, too. Here is an example:
class MyClass
{
int numberOne;
double numberTwo;
public:
friend std::ostream& operator<<(std::ostream &out, const MyClass& myClass);
friend std::istream& operator>> (std::istream& in, MyClass& myClass);
};
// Since operator<< is a friend of the MyClass class, we can access MyClass's members directly.
std::ostream& operator<<(std::ostream &out, const MyClass& myClass)
{
out << myClass.numberOne << ' ' << myClass.numberTwo;
return os;
}
// Since operator>> is a friend of the MyClass class, we can access MyClass's members directly.
std::istream& operator>> (std::istream& in, MyClass& myClass)
{
in >> myClass.numberOne;
in >> myClass.numberTwo;
return in;
}
int main()
{
MyClass myClass;
std::cin >> myClass;
std::cout << myClass;
}
Because of operator overloading.
In your case, including <iostream> will include <string>, a specialization of std::basic_string. And std::basic_string has the non-member functions operator<< and operator>> defined.
Similarly, you can also overload operator<< and operator>> for your own custom types.

How to call a operator overloaded function from other functions / methods in c++?

I have another class object in my class. Ex:
ParkingMeter.h
class ParkingMeter
{
private:
ParkedCar pCar;
int minutesPurchased = 0;
public:
friend std::istream& operator >> (std::istream, ParkingMeter&);
};
ParkedCar.h
class ParkedCar
{
private:
std::string maker;
std::string model;
std::string color;
int licenseNumber = 0;
int minutesParked = 0;
public:
friend std::istream& operator >> (std::istream&, ParkedCar&);
friend std::ostream& operator << (std::ostream&, ParkedCar&);
};
So, when I enter the data for ParkingMeter object with it's respective operator overloaded, I want to call the overloaded function for the ParkedCar object aswell.
This is what I've got. The operator overloaded function for the ParkingMeter:
std::istream& operator>>(std::istream is, ParkingMeter& obj)
{
cout << "How many minutes to buy? ";
is >> obj.minutesPurchased;
cout << "Enter the information about your car:\n";
is >> obj.pCar;
return is;
}
But in my main file, the following code don't word:
ParkingMeter temp;
std::cin >> temp;
Thank you.
Solution
Thanks to #L. F. for pointing my silly mistake. :D
I've forgotten to use the & after std::istream in the arguments for the function:
friend std::istream& operator >> (std::istream, ParkingMeter&);
Now its works fine:
friend std::istream& operator >> (std::istream&, ParkingMeter&);

making a class readable with >> and writable with << operators

I have an assignment question for my object orientated programming course that asks for the creation of a class.
I am a little stuck on this part of the questions
The class must, however, be readable using the >> operator and writable using the << operator. Do not use a friend function to overload the operators. Instead create suitable read and write methods and then overload the operators using a non-friend function.
class MyClass
{
public:
void ReadFrom(std::istream &is)
{
// read values from 'is' as needed...
}
void WriteTo(std::ostream &os) const
{
// write values to 'os' as needed...
}
};
std::istream& operator>>(std::istream &is, MyClass &cls)
{
cls.ReadFrom(is);
return st;
}
std::ostream& operator<<(std::ostream &os, const MyClass &cls)
{
cls.WriteTo(os);
return os;
}

Overloading operator for programming exercise

I'm in a programming class and need overloading explained to me. Simple question so hopefully I'll get an answer pretty quick. My understanding is that overloading an operator allows it to be used on a class. If that is true, then how would I overload >> to work with a class? I'm working on a small program to test out this idea and i'll post it here
#include <iostream>
#include <cstdlib>
#include "data.h"
using namespace std;
int main()
{
data obj;
cout << "What is the Number?" << endl;
cin >> obj;
system("pause");
return 0;
}
class data
{
public:
data operator >> (int);
private:
};
This page tells you mostly everything you need to know about operator overloading.
In short, nearly every operator in C++ can be overloaded for user-defined types. Some operators, like +, -, or >> must be defined outside of a class since they are free-standing, whereas others like copy assignment (=), must be defined within.
For your case, overloading the >> operator can be done in the following manner:
istream& operator>>(istream& in, data& d){
// Code here
return in;
}
Where it says "Code here", place the code you need to read into the data object.
For example, let us pretend that we were reading into a Point object with an x coordinate and a y coordinate. It is formatted in the stream like so: "(x,y)". The operator overload might look like this:
istream& operator>>(istream& in, Point& p){
char c;
in >> c;
if(c != '('){
in.clear(ios_base::failbit);
return in;
}
in >> p.x >> c >> p.y >> c;
return in;
}
This is just an example with minimal format checking, but hopefully it is enough to get you started.
Note that if members in your class are private, then you should friend the istream operator in the class definition:
class data{
...
public:
friend istream& operator>>(istream&, data&);
}
case1: no need to access private data
data.h.
class data {
public:
int i;
};
std::ostream& operator>> (std::istream&, data&); // better make operator >>
// a nonmember function
// if it doesn't need access
// to private data
data.cpp
#include "data.h"
std::istream& operator>> (std::istream& is, data& d) {
is>>d.i; // here we do some logic, we do what it means to do >> on
return is; // an instance of your data class and return reference to istream
}
case2: there is a need to access private data
data.h.
class data {
private:
int i;
friend std::ostream& operator>> (std::istream&, data&);
};
data.cpp
#include "data.h"
std::istream& operator>> (std::istream& is, data& d) {
is>>d.i; // here we do some logic, we do what it means to do >> on
return is; // an instance of your data class and return reference to istream
}
If you want to bolster your understanding of what operator overloading is, consider that essentially all operators on objects (such as "+", "++", "==", "!=", etc) are member functions.
Challenge yourself to recognize Obj a, b; a = b; as Obj a; Obj b; a.operator=(b);.
Overloading is purely providing a non-default implementation.
Here is a [terrible] overload of the cast-to-const-char* operator:
class BadWolf {
const char* m_text;
public:
BadWolf(const char* text) : m_text(text) {}
// if you really want the original text and ask for it with this function...
const char* tardisTranslation() const { return m_text; }
// but if you try to use me as a const char*...
operator const char* () const { return "bad wolf"; }
};
int main(int argc, const char* argv[]) {
BadWolf message("hello, sweetie");
std::cout << "Message reads: " << (const char*)message << std::endl;
std::cout << "Tardis translation: " << message.tardisTranslaction() << std::endl;
return 0;
}
I think this is what you want.
class data
{
friend istream& operator>>( istream&, data& );
private:
int data;
};
istream& operator>>( istream& in, data& d )
{
return in >> d.data;
}

Operator overloading >>

I am very new to C++ operator overloading and having some teething trouble.
I have defined:
void Graph::operator>>(const char* param)
The above function had to accept a string as input and then perform certain actions on the string. How do I call this function ? In what ways can I use it?
If you want to define operator so that you can do:
cin >> myGraph
cout << myGraph
You need to do something like this example below:
struct Entry
{
string symbol;
string original;
string currency;
Entry() {}
~Entry() {}
Entry(string& symbol, string& original, string& currency)
: symbol(symbol), original(original), currency(currency)
{}
Entry(const Entry& e)
: symbol(e.symbol), original(e.original), currency(e.currency)
{}
};
istream& operator>>(istream& is, Entry& en);
ostream& operator<<(ostream& os, const Entry& en);
Then implement operators:
istream& operator>>(istream& is, Entry& en)
{
is >> en.symbol;
is >> en.original;
is >> en.currency;
return is;
}
ostream& operator<<(ostream& os, const Entry& en)
{
os << en.symbol << " " << en.original << " " << en.currency;
return os;
}
Note: in this case the Entry is struct so it's members are public. If you don't want to make them public you can define the operator methods as friends so that they can access private members of Entry.
Here is how Entry would look like if it's members were not public:
struct Entry
{
private:
string symbol;
string original;
string currency;
public:
Entry() {}
~Entry() {}
Entry(string& symbol, string& original, string& currency)
: symbol(symbol), original(original), currency(currency)
{}
Entry(const Entry& e)
: symbol(e.symbol), original(e.original), currency(e.currency)
{}
friend istream& operator>>(istream& is, Entry& en);
friend ostream& operator<<(ostream& os, const Entry& en);
};
Graph myGraph;
myGraph >> "bla";
Note that yours is a weird use of operator>>(). Normally it's used like this:
NumericObject NumericObject::operator>>(NumericObject const& operand) const;
// bitshifts to the right
and
std::istream& operator>>(istream& in, StreamableObject& obj);
// parses a string representation of obj
I'm guessing what you are actually trying to do is be able to write code like this:
cin >> myGraph;
cout << myGraph;
Note that the graph object is not actually the object that gets its method called.
In this case, what you actually want to do is overload the global operator>> functions:
std::istream& operator>> (std::istream&, graph&);
std::ostream& operator<< (std::ostream&, const graph&);
If you're new to this, you picked a rather interesting (read as "not simple") problem to try to solve.
The operator overloads are not exactly functions. They are called indirectly when the compiler attempts to resolve code that looks something like this:
Graph g = new Graph();
g >> "do something";
I recommend you do NOT do this. Operator overloading can lead to VERY difficult bugs to troubleshoot, thanks to side effects. They are also hard on anyone who has to maintain your code (which might be you after you forgot why you did this).
Use operator overloads only when the meaning and use of them is intuitive.