views:

73

answers:

1

This may be a novice question, but I can't figure it out by inspecting the book I have. The class's constructor initializes two doubles, and I want the following code to output those two doubles with <<.

Complex x( 3.3, 1.1 );

cout << "x: " << x;

After this I need to overload >> to accept two doubles into these. This is my first question here, so if my information provided is lacking inform me

EDIT: I now have for the constructor and overloading statement this:

#include "Complex.h"

Complex::Complex( double realPart, double imaginaryPart )
: real( realPart ),
imaginary( imaginaryPart )
{

}

std::istream& operator>>(std::istream& strm, const Complex &c)
{
   double r,i;
   strm >> r >> i;
   c = Complex(r,i);
   return strm;
}

I know I have to change the "const Complex &c" and the "c = Complex(r,i);" but I'm not sure how to go about it. Also, I will say here that this is not about the std library's Complex class, although it is based on the same idea. So far everyone has been a great help, but I have a case of the dumb today.

+2  A: 

operator<< :

std::cout is an std::ostream object, so you have to overload operator<< for ostream, which takes std::complex<double> as an argument, assuming you use std::complex<double> from the standard header complex. Since you shouldn't make internal changes to standard containers and classes, make it standalone.

#include <iostream>
#include <complex>

std::ostream& operator<<(std::ostream& strm, const std::complex<double>& c)
{
    strm << "real: " << c.real() << "imag: " << c.imag();
    return strm;
}

operator>> :

operator>> takes a std::istream object, which does the opposite of what std::ostream does. If you use streams for serialization like this, it's a good idea to enable exceptions for them too. Usually you only want to throw on std::ios::badbit.

#include <iostream>
#include <complex>

std::istream& operator>>(std::istream& strm, std::complex<double>& c)
{
    double r,i;
    strm >> r >> i;
    c = std::complex<double>(r,i);
    return strm;
}

If you needed access to internal members of the class, you would define the overloaded function as a friend. But since std::complex::real() and std::complex::imag() are a part of the public interface, that's not needed here. And for the istream example, we simply invoke the copy-constructor which is also a part of the public interface.

I assumed you wanted to use cin and cout here. But if you wanted to overload the operators for something else, the same applies. If you implement the operators inside a class definition, you have access to the this pointer, hence the operator function should only take one argument.

Mads Elvheim
I think he is writing his own Complex class (from a tutorial), not modifying the existing one.
Mark Byers
Probably, but this is how you do it no matter what.
David Thornley
What Mark said, but the ostream and istream parts are still right-looking. I don't know what std::complex<double> is.
R. Daneel Olivaw
It doesn't matter really. Because the operators he seem interested in are operator<< and operator>> for ostream and istream, so it needs to be made outside the class anyway. Unless you want cout and cin to appear on the right side. And that does not work if you want chaining.
Mads Elvheim
@R. Daneel Olivaw: std::complex is a class for complex numbers with one real part and one imaginary part. You'll find it in the header <complex>.
Mads Elvheim
R. Daneel Olivaw: I'm not sure if you understood this already, but do *not* #include <complex> in your file. You can look in the file to see how it is implemented, but if you are writing your own Complex class then you should assume that std::complex does not exist.
Mark Byers
Mads Elvheim's original comment was more useful than I thought. Figured out that I was supposed to be using a friend function in this situation.
R. Daneel Olivaw
Feel free to use your "accept answer" button :-)
Mads Elvheim