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.
Related
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.
If i want to overload the operator ">>" and this is the line inside my .h file
friend istream &operator >> (istream& input,const Money&m2);
Do I want for instance
friend istream &operator >> (istream& input,const Money&m2){
input >> m2.dollar;
return input;
}
into my header file or into my class file. If i were to put it into my class file how would the function be called? Would something like this be okay?
const Money Money::&operator >> (istream& input,const Money&m2)
The class name is "Money.cpp"
The input streaming operator takes a reference to a non-const std::istream, and a reference to a non-const object into which the data is to be read. You can define it as a friend of the class for efficiency (direct access to the member variables), but if you already provide efficient mechanisms for setting those values, you may want to consider whether it needs to be a friend at all.
In the example below, I define a class Money, which represents some value (as a double-precision floating-point value, which is pretty bad, but just an example) and the ISO currency code (as a std::string). I then define an input streaming operator that reads input in the format "13.99 GBP" and an output streaming operator that writes the values in the same format.
Live example: http://coliru.stacked-crooked.com/a/d3e24b4fd697f773
money.hpp
class Money {
public:
Money(double value, const std::string& code);
const std::string& currencyCode() const;
double value() const;
friend std::istream& operator>>(std::istream&, Money&);
private:
double value_;
std::string code_;
};
std::istream& operator>>(std::istream& in, Money& m);
std::ostream& operator<<(std::ostream& out, const Money& m);
money.cpp
Money::Money(double value, const std::string& code)
: value_(value), code_(code) {}
const std::string& Money::currencyCode() const {
return code_;
}
double Money::value() const {
return value_;
}
std::istream& operator>>(std::istream& in, Money &m) {
in >> m.value_ >> m.code_;
return in;
}
std::ostream& operator<<(std::ostream& out, const Money& m) {
out << m.value() << " " << m.currencyCode();
return out;
}
Some points to bear in mind:
In general, the output streaming operator need not be a friend; there is usually a way to access the information it needs through the public member functions of the class, without losing efficiency.
The input streaming operator is a friend only for efficiency reasons; we can stream directly into the member variables.
For the input streaming operator, the second parameter (the object you're reading into) must not be const - an input operation changes the object being read into.
For the output streaming operator, the second parameter (the object you're writing out) should be const - an output operation should not change the object being written out.
If the constructor performs some non-trivial validation (e.g. checking that the std::string contains a valid ISO currency code), we should not bypass that validation by reading directly into the member variable in our input streaming operator. Instead, we should read into a local double and a local string, then construct a Money object, handing validation off to the already-written constructor (see the example below; the header is identical, except for removing the friend declaration from the class).
Live example: http://coliru.stacked-crooked.com/a/233ac7c17e51f612
money.cpp (validation in constructor)
Money::Money(double value, const std::string& code)
: value_(value), code_(code) {
if (code_ != "GBP") throw std::runtime_error("Must be GBP");
}
const std::string& Money::currencyCode() const {
return code_;
}
double Money::value() const {
return value_;
}
std::istream& operator>>(std::istream& in, Money &m) {
double value(0.0);
std::string code;
in >> value >> code;
m = Money(value, code);
return in;
}
std::ostream& operator<<(std::ostream& out, const Money& m) {
out << m.value() << " " << m.currencyCode();
return out;
}
If you put it in your header any change in the function definition requires recompilation of any files that include it. If you define it in the .cpp file then you don't and the linker will sort out calling it.
I don't know what is bothering you so have this example and see if it clears your doubt.
Run Here: http://ideone.com/K90L13
.h
#include <iostream>
#include <istream>
using namespace std;
class A{
int p;
public:
friend istream & operator >> (istream&,A&);
friend ostream & operator << (ostream&,A&);
};
.cpp
istream & operator >> (istream &input, A &obj){
input >> obj.p;
return input;
}
ostream & operator << (ostream &output, A &obj){
output << obj.p;
return output;
}
int main(){
A a;
cin >> a;
cout << a;
}
answered.
Function name in class field should be
std::istream &operator >> (istream& input,const Money&m2){}
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;
}
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;
}
I have class Person (first name, last name, address, age) and overloaded operators << and >> to use it with filestreams:
ostream& operator<< (ostream& outStream, Person& person)
{
...
}
istream& operator>> (istream& inStream, Person& person)
{
...
}
It works fine - I can read from and write to file easily, but I have added two classes inherited from Person: Student and Worker.
I wrote overloaded operators for them, very similar to those above:
ostream& operator<< (ostream& outStream, Worker& worker)
{
...
}
istream& operator>> (istream& inStream, Worker& worker)
{
...
}
ostream& operator<< (ostream& outStream, Student& student)
{
...
}
istream& operator>> (istream& inStream, Student& student)
{
...
}
Only difference are two more fields in each class. The problem is, that when I use overloaded operators with either Student or Worker it seems my compiler uses operators for person. Probably it makes hidden conversion from Student or Worker to Person, but as a result there are no those additional fields written to the file.
offstream << People works just the same as offstream << Students or offstrem Workers.
Maybe placing overloaded operators declarations for inherited classes first, and for Person later in the code would solve the issue, but i don't find it an elegant solution.
If you have some ideas how to manage with the problem above, I would appreciate.
Two things. First, make your operators take references to const, like this:
ostream& operator<< (ostream& outStream, const Person& person)
To solve your problem, a common pattern is to provide your types with a protected virtual toString method, and have the operator just call that. You can then just overload this method in the sub-classes, and even reuse the super-class implementation if you just want to append some values to the string.
Example:
class Person {
// other stuff
protected:
virtual std::string toString();
friend ostream& operator<< (ostream& outStream, const Person& person)
};
ostream& operator<< (ostream& outStream, Person& person)
{
ostream << person.toString();
return outStream;
}
Edit
Actually, I like larsmans suggestion even better:
class Person {
// other stuff
protected:
virtual void print(ostream & stream) const;
friend ostream& operator<< (ostream& outStream, const Person& person)
};
ostream& operator<< (ostream& outStream, Person& person)
{
person.print(outStream);
return outStream;
}
This will be easier to implement than the toString idea, because you need no temporary stringstream or anything like that to build the string.
Most probably the code which calls the << operator accesses the object through a pointer or reference to Person, thus calling the operator for the Person type. The usual way of handling this is to provide a virtual method on the parent (i.e. Person) class which does the writing (getting the stream as an argument), and have the operator<< call this method to do the work. You need to provide the operator<< only for the parent class, the virtual dispatch mechanism will take care of choosing the right method for the object provided.
class Person {
// ...
protected:
virtual ostream& stream_write(ostream&) const; //override this in child classes
virtual istream& stream_read(istream&); //this too
public:
friend ostream& operator<< (ostream& stream, const Person& obj)
{ return obj.stream_write(stream); }
friend istream& operator>> (istream& stream, Person& obj)
{ return obj.stream_read(stream); }
};
Your operators could call a virtual method. Something like this :
struct A
{
virtual ~A(){}
virtual std::ostream& Print( std::ostream &os ) const
{
// print what you want
return os;
}
};
struct B : A
{
virtual ~B(){}
virtual std::ostream& Print( std::ostream &os ) const
{
// print what you want
return os;
}
};
Then create the operator<< only for the base class :
std::ostream& operator<<( std::ostream &os, const A &a)
{
return a.Print(os);
}
I usually call a virtual function streamIn and streamOut in the overloaded streaming operators, in that way I can actually create a template streaming function that works for all classes with streamIn and streamOut functions.