This question stems from a larger code I am working on but hopefully I can break it down to simplify:
Say I have two classes, one which holds 2 integer variables, and another which contains a vector that holds the first class
class TwoInts {
int num1;
int num2;
}
class NumHold {
std::vector<TwoInts> numVector;
}
How would I go about printing my numHold class exactly? I know I would have to provide an overloaded stream operator
std::ostream &operator<< (std::ostream &out, const NumHold &myNumHold){;}
But I'm a little confused as to the syntax regarding how I would print out these integers from the vector. I also understand that in order for the stream operator to work I would have to add it to my class as a friend, I just wanted to keep my NumHold class as simplified as possible for the examples sake. Hopefully this was clear enough of an explanation, any help is appreciated
Treat out how you would treat std::cout, then return it at the end of the function:
std::ostream& operator<<(std::ostream& out, const NumHold &myNumHold){
//one possible output format
for(const auto& twoInt : myNumHold.numVector){
out << twoInt.num1 << ", " << twoInt.num2 << '\n'; //pretend out is std::cout
}
return out; //don't forget to return it at the end
}
If appropriate, declare the overload as a friend function within the NumHold class:
#include<iostream>
class NumHold {
private:
std::vector<TwoInts> numVector;
public:
//friend operator overload declaration
friend std::ostream& operator<<(std::ostream& out, const NumHold& myNumHold);
};
In your example, it is appropriate, as the overload function accesses private variables.
You need to be able to access the members of each TwoInts in order to print them. One way to do this is to make them public.
class TwoInts {
public: //lets NumHold access variables to print
int num1;
int num2;
};
class NumHold {
public:
std::vector<TwoInts> numVector;
friend std::ostream& operator << (std::ostream& out, const NumHold& myNumHold) {
for (const TwoInts& ti : myNumHold.numVector) {
out << "(" << ti.num1 << ", " << ti.num2 << ")" << std::endl;
}
return out;
}
};
You can also consider adding printing methods to your classes:
#include<iostream>
class TwoInts {
private:
int num1;
int num2;
public:
void printnum1(){
std::cout << num1;
}
void printnum2(){
std::cout << num2;
}
}
class NumHold {
private:
std::vector<TwoInts> numVector;
public:
//this function prints the private attributes of the class
void printnumVector(){
for (int i = 0; i < numVector.size(); i++){
std::cout << numVector[i].printnum1() << " " << numVector[i].printnum2() << std::endl;
}
}
};
Related
Error ocurred with the following try to operator overloading:
#include<iostream>
#include<string>
#include<ostream>
using namespace std;
class Dollar
{
private:
float currency, mktrate, offrate;
public:
Dollar(float);
float getDollar() const;
float getMarketSoums() const;
float getofficialSoums() const;
void getRates();
// In the following function I was trying to overload "<<" in order to print all the data members:
friend void operator<<(Dollar &dol, ostream &out)
{
out << dol.getDollar() << endl;
out << dol.getMarketSoums() << endl;
out << dol.getofficialSoums() << endl;
}
};
Dollar::Dollar(float d)
{
currency = d;
}
float Dollar::getDollar() const
{
return currency;
}
float Dollar::getMarketSoums() const
{
return mktrate;
}
float Dollar::getofficialSoums() const
{
return offrate;
}
void Dollar::getRates()
{
cin >> mktrate;
cin >> offrate;
}
int main()
{
Dollar dollar(100);
dollar.getRates();
// In this line I am getting the error. Could you please help to modify it correctly?
cout << dollar;
system("pause");
return 0;
}
You have to pass std::ostream object as the first parameter to the insertion operator << not as the second one as long as you are calling it that way:
friend void operator << (ostream &out, Dollar &dol);
You should make the object passed in to the insertion operator constant reference as long as this function is only prints and not intending to modify the object's members:
friend void operator << (ostream &out, const Dollar& dol);
So pass by reference to avoid multiple copies and const to avoid unintentional modification.
If you want to invoke to get it work the way you wanted you can do this:
friend void operator<<(const Dollar &dol, ostream &out){
out << dol.getDollar() << endl;
out << dol.getMarketSoums() << endl;
out << dol.getofficialSoums() << endl;
}
And in main for example:
operator << (dollar, cout); // this is ok
dollar << cout; // or this. also ok.
As you can see I reversed the order of calling the insertion operator to match the signature above. But I don't recommend this, it is just to understand more how it should work.
Consider the following example:
#include <iostream>
class A {
const int i;
const int j;
public:
A(int i_, int j_) : i(i_), j(j_) {}
std::ostream& operator<<(std::ostream& o) const {
o << "i is " << i << ", j is " << j;
return o;
}
};
std::ostream& operator<<(std::ostream& o, const A& a ) {
o << "This is A: ";
a.operator<<(o);
return o;
}
int main() {
A a(0,42);
std::cout << a << std::endl;
return 0;
}
It will generate the following output:
This is A: i is 0, j is 42
The output is correct but I don't like how I am calling A's original operator<<.
I am trying to figure out how to properly define that operator, so it could be called this way:
o << "This is A: " << (some magic)a;
instead of
o << "This is A: ";
a.operator<<(o);
I have tried various ways but either I get to ambiguity issues or getting an address of the std::cout and broken string. Notice that the result std::ostream& of A::operator<< is a remnant of my tests. In the example above it would suffice to use void.
Is it possible without creating an intermediate class B that derives from class A and defines its own operator<< (class NiceOutputOfA : public A {...};) ?
Binary operators defined in-class always have the class as the left-hand side operand. Which means you cannot implement stream insertion/extraction in-class.
Probably the most common way is to implement the operator as a friend defined inline in the class.
Another reasonably common way is to provide a named streaming function in the class, and an out-of-class streaming operator which calls that function. You almost did that, but named that function operator <<.
The closest resolution I came to is by creating an intermediate class:
class Decorate {
const A& a;
public:
Decorate(const A& a_) : a(a_) {}
friend std::ostream& operator<<(std::ostream& o, const PrintA& pa) {
o << "This is A: " << pa.a;
return o;
}
};
and having it printed this way:
int main() {
A a(0,42);
std::cout << Decorate(a) << std::endl;
return 0;
}
I was looking for something prettier but based on Angew's answer I lost hope to have it done suing proper operator<< declaration.
Thanks for all your help!
Marking Angew's response as the answer.
I have a class A, for which I have defined an (overloaded) stream insertion operator. I publicly derive a class B from this class A, which has an additional data member. Therefore I'll need to redefine the overloaded stream insertion operator for the derived class and I've do it this way:
#include <iostream>
using namespace std;
class A {
int i;
char c;
public:
A(int i = 0, char c = ' ') {
this->i = i;
this->c = c;
}
friend ostream& operator << (ostream&, const A&);
};
class B : public A {
double d;
public:
B(int i = 0, char c = ' ', double d = 0.0) : A(i, c), d(d) {}
friend ostream& operator << (ostream&, const B&);
};
ostream& operator << (ostream& out, const A& a) {
out << "\nInteger: " << a.i << "\nCharacter: " << a.c << endl;
return out;
}
ostream& operator << (ostream& out, const B& b) {
out << b;
out << "\nDouble: " << b.d << endl;
return out;
}
int main() {
A a(10, 'x');
B b(20, 'y', 5.23);
cout << b;
return 0;
}
Question-1: Is this an appropriate technique of doing so? If not, kindly let me know where I'm going wrong.
Question-2: On running, this program crashes. Why so?
One common way to support this is to have the overloaded operator invoke a virtual member function:
class A {
public:
virtual std::ostream &write(std::ostream &os) const {
// write self to os
os << "A\n";
return os;
}
};
class B : public A {
public:
virtual std::ostream &write(std::ostream &os) const {
// write self to os
// This can use the base class writer like:
A::write(os);
os << "B\n";
return os;
}
};
Then the operator overload just invokes that member function:
std::ostream &operator<<(std::ostream &os, A const &a) {
return a.write(os);
}
Since write is virtual and you're passing the A by (const) reference, this invokes the correct member function based on the actual type (i.e., A::write if the object is really an instance of A, and B::write if it's an instance of B).
For example, we could exercise these something like this:
int main() {
A a;
B b;
std::cout << a << "\n";
std::cout << b << "\n";
}
...which produces output like this:
A
A
B
In real use, you probably want to make the write functions protected, and make the operator<< a friend of A.
The program crashes because your second insertion operator calls itself:
ostream& operator << (ostream& out, const B& b) {
out << b; // <--YIKES!
out << "\nDouble: " << b.d << endl;
return out;
}
Generally this is a good approach, although I prefer to give the classes a public virtual print(ostream&) const function, and have the insertion operator call that.
I learnt how to do operator overloading of Stream Insertion Operator. But one doubt remains.
#include<iostream>
class INT
{
int i;
friend std::ostream& operator<<(std::ostream&,INT&);
public:
INT():i(100){}
};
std::ostream& operator<<(std::ostream& obj,INT & data)
{
obj<<data.i;
return obj;
}
int main()
{
INT obj;
std::cout<<obj;
}
What significance return obj; has?
Do that return have any use further?
Are We forced to do that return because of the syntax of the operator<< without any usefulness?
Remember how you can write code like this:
cout << "The data is: " << somedata << endl;
This is actually the same as:
((cout << "The data is: ") << somedata) << endl;
For this to work, the << operator has to return the stream.
I'd like to control what is written to a stream, i.e. cout, for an object of a custom class. Is that possible in C++? In Java you could override the toString() method for similar purpose.
In C++ you can overload operator<< for ostream and your custom class:
class A {
public:
int i;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.i << ")";
}
This way you can output instances of your class on streams:
A x = ...;
std::cout << x << std::endl;
In case your operator<< wants to print out internals of class A and really needs access to its private and protected members you could also declare it as a friend function:
class A {
private:
friend std::ostream& operator<<(std::ostream&, const A&);
int j;
};
std::ostream& operator<<(std::ostream &strm, const A &a) {
return strm << "A(" << a.j << ")";
}
You can also do it this way, allowing polymorphism:
class Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Base: " << b << "; ";
}
private:
int b;
};
class Derived : public Base {
public:
virtual std::ostream& dump(std::ostream& o) const {
return o << "Derived: " << d << "; ";
}
private:
int d;
}
std::ostream& operator<<(std::ostream& o, const Base& b) { return b.dump(o); }
In C++11, to_string is finally added to the standard.
http://en.cppreference.com/w/cpp/string/basic_string/to_string
As an extension to what John said, if you want to extract the string representation and store it in a std::string do this:
#include <sstream>
// ...
// Suppose a class A
A a;
std::stringstream sstream;
sstream << a;
std::string s = sstream.str(); // or you could use sstream >> s but that would skip out whitespace
std::stringstream is located in the <sstream> header.
The question has been answered. But I wanted to add a concrete example.
class Point{
public:
Point(int theX, int theY) :x(theX), y(theY)
{}
// Print the object
friend ostream& operator <<(ostream& outputStream, const Point& p);
private:
int x;
int y;
};
ostream& operator <<(ostream& outputStream, const Point& p){
int posX = p.x;
int posY = p.y;
outputStream << "x="<<posX<<","<<"y="<<posY;
return outputStream;
}
This example requires understanding operator overload.