I'm doing a tutorial on C++ to really dig into the nitty-gritty of it, because frankly it's an awesome and powerful language. I'm still fairly new at it though, and I'm having issues with my operator overloading for the ostream operator.
Since this is a tutorial I'm trying to keep my code as organized and modular as possible to avoid confusion. There are 3 layers to my code:
main.cpp - runs the Exercises.
Exercises.cpp/Exercises.h - contains static functions for the exercises.
ComplexNumber.cpp/ComplexNumber.h - represents a complex number object in line with the tutorial.
Main is fairly simple: set of calls to Exercises::ExerciseName().
Exercises.cpp:
#include "Exercises.h"
void Exercises::ComplexNumberClass() {
ComplexNumber c; /** Runs the blank constructor */
ComplexNumber c1(2, 3); /** Runs the args-filled constructor */
ComplexNumber c2 = c1; /** Runs the copy constructor */
c = c2;
cout << c1 << endl;
}
The header file only has the header for that function as a public static void function, i.e. callable and executable. The ComplexNumber files are where I think the problem is (please correct me if I'm wrong):
ComplexNumber.cpp (without constructors and accessors):
#include "ComplexNumber.h"
using namespace ComplexNumbers;
using namespace std;
ostream& operator<< (ostream& out, ComplexNumber& num){
out << "(" << num.GetReal() << ", " << num.GetImaginary() << ")";
return out;
}
const ComplexNumber &ComplexNumber::operator=(const ComplexNumber &num) {
cout << "Using assignment operator override" << endl;
real = num.real;
imaginary = num.imaginary;
return *this;
}
ComplexNumber.h:
#ifndef OPERATOROVERLOADING_COMPLEXNUMBER_H
#define OPERATOROVERLOADING_COMPLEXNUMBER_H
#include <iostream>
using namespace std;
namespace ComplexNumbers {
class ComplexNumber {
private:
double real;
double imaginary;
public:
ComplexNumber();
ComplexNumber(double real, double imaginary);
ComplexNumber(const ComplexNumber &num);
const ComplexNumber &operator=(const ComplexNumber &num);
double GetReal() const {
return real;
}
double GetImaginary() const {
return imaginary;
}
};
ostream &operator<<(ostream& out, ComplexNumber& num);
}
#endif //OPERATOROVERLOADING_COMPLEXNUMBER_H
When I build this, it's telling me that I have an "undefined reference to 'cave_of_programming::operator<<(std::ostream&, cave_of_programming::ComplexNumber&)'. The method headers match, and I'm building with Jetbrains CLion.
My research suggests that the problem is in the linker, but I've looked at my CMakeLists.txt and found that it is linking up all of the appropriate files.
SOURCE_FILES main.cpp Exercises.cpp Exercises.h ComplexNumbers/ComplexNumber.cpp ComplexNumbers/ComplexNumber.h
Does anybody have an idea as to why this isn't working? What am I missing?
The problem is that you defined ostream &operator<<(ostream& out, ComplexNumber& num) inside the class. This doesn't make much sense to the compiler because it knows to override the operator<< when it gets an ostream object and a class of some type,
but the way you implemented it, it gets the ostream, a ComplexNumber, and another ComplexNumber as the 'this' reference.
In order to correctly overload a binary operator you have two options:
Define the operator inside the class, and give it only the ostream as parameter
class ComplexNumber
{
...
ostream &operator<<(ostream& out) const;
};
Or define the operator outside the class and give it both the parameters:
class ComplexNumber
{
...
};
ostream &operator<<(ostream& out, const ComplexNumber& num);
Note that in the second implementation, you need to add the function as a friend of the class if you want to access any private members.
Also note, that it's a good idea to use const here like I put in the examples, otherwise you won't be able to use the operator on const ComplexNumbers.
Related
I started to learn C++ recently and i ran into this trouble with using overloaded input operator >>.
I am writing a class to describe a Complex number.
My problem is: If i put my main() in the Complex.cpp, my program run normally. But if i create a new file main.cpp and put my main() there i ran into error.
error: invalid operands to binary expression ('std::istream' (aka 'basic_istream') and 'Complex')
candidate function not viable: no known conversion from 'std::istream' (aka 'basic_istream') to 'std::istream *' (aka 'basic_istream *') for 1st argument; take the address of the argument with &
(There are a lots more error bellow but they point to istream so i don't think that is the problem)
This is my header file:
#include <iostream>
using namespace std;
#ifndef HEADER_H
#define HEADER_H
#endif // HEADER_H
class Complex
{
public:
double _real;
double _imag;
public:
Complex(double, double);
double getReal() const;
double getImag() const;
void setReal(double);
public:
Complex operator=(const Complex&);
Complex * operator+(const Complex&);
Complex * operator+(const double&);
friend Complex * operator+(const double&, const Complex&);
Complex * operator++();
Complex * operator++(int);
Complex * operator--();
Complex * operator--(int);
operator double() const;
friend ostream &operator<<(ostream*, const Complex&);
friend istream &operator>>(istream*, Complex&);
};
And i created Complex.cpp to identify the function:
#include "Complex.h"
using namespace std;
Complex::Complex(double a, double b)
{
this->_real = a;
this->_imag = b;
}
double Complex::getReal() const{...}
void Complex::setReal(double x){...}
double Complex::getImag() const{...}
Complex Complex::operator=(const Complex& other){...}
Complex * Complex::operator+(const Complex& other){...}
Complex * Complex::operator+(const double &other){...}
Complex * operator+(const double &first, const Complex &second){...}
Complex * Complex::operator++(){...}
Complex * Complex::operator++(int){...}
Complex * Complex::operator--(){...}
Complex * Complex::operator--(int){...}
Complex::operator double() const{...}
ostream &operator<<(ostream &output, const Complex &comp)
{
output << comp._real << " + " << comp._imag << "i";
return output;
}
istream &operator>>(istream &input, Complex &comp)
{
input >> comp._real >> comp._imag;
return input;
}
This is my main:
#include "Complex.h"
int main()
{
Complex com4(0,0);
cout << "Input Complex: ";
cin >> com4;
cout << com4 <<endl;
}
You declared io operators with pointers (which is wrong)
friend ostream &operator<<(ostream*, const Complex&);
friend istream &operator>>(istream*, Complex&);
but implemented it correctly with references.
friend ostream &operator<<(ostream&, const Complex&) {...}
friend istream &operator>>(istream&, Complex&) {...}
When you have your main() in Complex.cpp, the compiler can see those correct implementations (that are not defined in any header).
If you have your main() somewhere else, the compiler can only see the declarations in the header, which have the wrong signature.
Solution will be to fix the declarations of operator<< and operator>> in the header, so that they match the implementation.
As a note and as already mentioned in the comments: Your other operator-overloads should return Complex & or Complex not Complex *. Take a look at std::complex or this page, detailing operator overloading to see what the canoncial implementations look like.
I created two classes and a constructor in each. Type followed a new class and constructors friends functions of the classes before.
#include <iostream>
using namespace std;
class clsAtmosfericConditions;
class clsDensity{
float density;
public:
clsDensity(){}
clsDensity(float densidad){
density = densidad;
}
friend istream& operator >>(istream &i, clsDensity &e);
friend ostream& operator <<(ostream &o, const clsDensity &s);
};
istream& operator >>(istream &i, clsDensity &e){
char sign;
i >> e.density >> sign >> sign >> sign >> sign >> sign >> sign;
return i;
}
ostream& operator <<(ostream &o, const clsDensity &s){
o << s.density << " Kg/m^3";
return o;
}
class clsDynamicViscocity{
double dynamicViscocity;
public:
clsDynamicViscocity(){}
clsDynamicViscocity(double viscocidadDinamica){
dynamicViscocity = viscocidadDinamica;
}
friend istream& operator >>(istream &i, clsDynamicViscocity &e);
friend ostream& operator <<(ostream &o, const clsDynamicViscocity &s);
};
istream& operator >>(istream &i, clsDynamicViscocity &e){
char sign;
i >> e.dynamicViscocity >> sign >> sign >> sign >> sign >> sign;
return i;
}
ostream& operator <<(ostream &o, const clsDynamicViscocity &s){
o << s.dynamicViscocity << " N/m^2";
return o;
}
class clsAtmosfericConditions{
friend clsDynamicViscocity::clsDynamicViscocity(double viscocidadDinamica);
friend clsDensity::clsDensity(float densidad);
public:
float kinematicViscocity();
};
float kinematicViscocity(){
float kinematicViscocity;
kinematicViscocity = dynamicViscocity/density; //Here is where IDE gives me the error
return kinematicViscocity;
}
The IDE displays an error in the function: error: 'dynamicViscocity' undeclares (first use this function)
I checked on some websites and I see no need to pass values by reference builder when you do the operation.
Couple of problems here.
dynamicViscocity is a member of class clsDynamicViscocity. kinematicViscocity is not a member of any class, but I suspect is is intended to be a member of clsAtmosfericConditions. Regardless, kinematicViscocity is not a member of clsDynamicViscocity, so in order to operate on dynamicViscocity, it needs an object of type clsDynamicViscocity to provide dynamicViscocity.
Second, the visibility (public, private, protected) of dynamicViscocity is not specified, so C++ defaults to the most restrictive, private. A private member cannot be seen except by the object and those the object has defined as friends.
So kinematicViscocity has no dynamicViscocity and even if it did, it cannot see dynamicViscocity.
Suggested solution
Change the definition of kinematicViscocity to
float clsAtmosfericConditions::kinematicViscocity(const clsDynamicViscocity & vis,
const clsDensity & den)
{
float kinematicViscocity;
kinematicViscocity = vis.getDynamicViscocity() / den.getDensity();
return kinematicViscocity;
}
to provide a clsDynamicViscocity to kinematicViscocity and add a getter function
double getDynamicViscocity() const
{
return dynamicViscocity;
}
to clsDynamicViscocity.
The same needs to be done to access density from clsDensity.
EDIT
Waaaait a second...
Finally figured out what you are trying to do here:
friend clsDynamicViscocity::clsDynamicViscocity(double viscocidadDinamica);
friend clsDensity::clsDensity(float densidad);
A class declares who they will allow to see and use their hidden internals. A class cannot declare who's hidden internals they can see. Think of it this way, Bob can be friends with Alice and show her his secrets, but Bob cannot force Alice to be his friend and show him her secrets. Alice has to make that decision herself.
What the above means is the two methods can can violate encapsulation and see the hidden internals of clsAtmosfericConditions. clsAtmosfericConditions cannot however see the internals of clsDynamicViscocity or clsDensity.
clsDynamicViscocity and clsDensity have to friend class clsAtmosfericConditions to allow clsAtmosfericConditions to see into them, not the other way around.
So
clsDensity()
{
friend class clsAtmosfericConditions;
...
}
and
clsDynamicViscocity()
{
friend class clsAtmosfericConditions;
...
}
Now change kinematicViscocity to look like this:
float clsAtmosfericConditions::kinematicViscocity(const clsDynamicViscocity & vis,
const clsDensity & den)
{
float kinematicViscocity;
kinematicViscocity = vis.dynamicViscocity / den.density;
return kinematicViscocity;
}
and you are golden.
The original solution with the getters is a better solution as it requires no friends whatsoever and is much less tightly coupled. The guts of clsDynamicViscocity and clsDensity can be radically changed without breaking clsAtmosfericConditions so long as the getter function prototypes remain the same and clsAtmosfericConditions is granted no more access to clsDynamicViscocity and clsDensity than is required to get data.
I'm trying to write a class that overloads the insertion operator but in my header file I get the error.
Overloaded 'operator<<' must be a binary operator (has 3 parameters)
Here is my code:
.h file
ostream & operator<<(ostream & os, Domino dom);
.cpp file
ostream & operator<< (ostream & os, Domino dom) {
return os << dom.toString();
}
I'm following a text book and this is what they use as an example but its not working for me.. Any suggestions?
You probably put your operator<< inside a class declaration. That means it takes an extra hidden parameter (the this parameter). You need to put it outside of any class declaration.
The insertion operator (<<) can be used as a member function or a friend function.
operator << used as a member function
ostream& operator<<(ostream& os);
This function should be invoked as :
dom << cout;
In general if you are using the operator as a member function, the left hand side of the operator should be an object. Then this object is implicitly passed as an argument to the member function. But the invocation confuses the user and it does not look nice.
operator << used as a friend function
friend ostream& operator<<(ostream& os, const Domino& obj);
This function should be invoked as :
cout << dom;
In this case the object dom is explicitly passed as a reference. This invocation is more traditional and user can easily understand the meaning of the code.
/*insertion and extraction overloading*/
#include<iostream>
using namespace std;
class complex
{
int real,imag;
public:
complex()
{
real=0;imag=0;
}
complex(int real,int imag)
{
this->real=real;
this->imag=imag;
}
void setreal(int real)
{
this->real=real;
}
int getreal()
{
return real;
}
void setimag(int imag)
{
this->imag=imag;
}
int getimag()
{
return imag;
}
void display()
{
cout<<real<<"+"<<imag<<"i"<<endl;
}
};//end of complex class
istream & operator >>(istream & in,complex &c)
{
int temp;
in>>temp;
c.setreal(temp);
in>>temp;
c.setimag(temp);
return in;
}
ostream &operator <<(ostream &out,complex &c)
{
out<<c.getreal()<<c.getimag()<<endl;
return out;
}
int main()
{
complex c1;
cin>>c1;
// c1.display();
cout<<c1;
//c1.display();
return 0;
}
hey, i got something that i cannot understand ,there are two types of solutions for overloading this operator 1 is including the friend at the start of the method and the other 1 goes without the friend.
i would very much like if some1 explain whats the difference between them advantages / disadvantages.
for example overloading the operator << in class rational:
class Rational:
{
private: int m_t,m_b;
...
friend ostream& operator<<(ostream& out,const Rational& r) // option 1
{ return out << r.m_t << "/" <<r.m_b;} // continue of option 1
ostream& operator<<(ostream& out,const Rational& r){return r.print();} // option 2
virtual ostream& print(ostream& out) const // continue of option 2
{ //
return out<<m_t << "/" << m_b;
} //
};
i was told that the second option isnt correct , if some1 can correct me about it i would much appriciate it.
thanks in advance.
The short answer: Option #2 actually isn't an option, but a syntax error, because it tries to define a binary operator as a member passing two operands.
The somewhat longer answer: If you make the second operand a free function (not a member of the class), this will work. Which one is preferable depends on the circumstances and your preferences. For starters: The disadvantage of the first is that it allows operator<< to access everything in Rational (including private helper functions), while the disadvantage of the second is that you introduce a function to the class' public API that nobody needs.
operator<< (for ostream) needs to be a free function (since the left-hand argument is a stream, not your class).
The friend keyword makes it a free function (a free function that has access to the private members).
However, if this functionality can be implemented in terms of the public interface, it is better to do so and just use a non-friend free function.
class Rational:
{
private: int m_t,m_b;
public:
...
virtual ostream& print(ostream& out) const
{
return out<<m_t << "/" << m_b;
}
};
ostream& operator<<(ostream& out,const Rational& r)
{
return r.print(out);
}
Consider a function that should output the num and den of Rational:
ostream& operator<<(ostream& out, const Rational& r)
{
return out;
}
Unfortunately, this is just a global function. Like any other global function, it cannot access the private members of Rational. To make it work with Rational objects, you need to make it friend of Rational:
class Rational
{
private: int m_t,m_b;
// ...
friend ostream& operator<<(ostream& out, const Rational& r);
};
ostream& operator<<(ostream& out, const Rational& r)
{
out << r.m_t << "/" <<r.m_b;
return out;
}
The friend ostream& operator<<(ostream& out, const Rational& r); inside Rational class indicates that ostream& operator<<(ostream& out, const Rational& r) function can directly use Rational's private members.
Now when you write:
Rational r(1, 2); // Say, it sets num and den
cout << r;
the following function call is made:
operator<<(cout, r);
Can you write operator<< as a member function of Rational? That's simply not possible because of the above conversion where cout has to be first parameter. If you make operator<< as a member of Rational:
class Rational
{
private: int m_t,m_b;
// ...
public:
ostream& operator<<(ostream& out) const
{
out << r.m_t << "/" <<r.m_b;
return out;
}
};
you need to call it this way:
Rational r(1, 2);
r.operator<<(cout);
which is ugly.
In a project I'm working on, I have a Score class, defined below in score.h. I am trying to overload it so, when a << operation is performed on it, _points + " " + _name is printed.
Here's what I tried to do:
ostream & Score::operator<< (ostream & os, Score right)
{
os << right.getPoints() << " " << right.scoreGetName();
return os;
}
Here are the errors returned:
score.h(30) : error C2804: binary 'operator <<' has too many parameters
(This error appears 4 times, actually)
I managed to get it working by declaring the overload as a friend function:
friend ostream & operator<< (ostream & os, Score right);
And removing the Score:: from the function declaration in score.cpp (effectively not declaring it as a member).
Why does this work, yet the former piece of code doesn't?
Thanks for your time!
EDIT
I deleted all mentions to the overload on the header file... yet I get the following (and only) error. binary '<<' : no operator found which takes a right-hand operand of type 'Score' (or there is no acceptable conversion)
How come my test, in main(), can't find the appropriate overload? (it's not the includes, I checked)
Below is the full score.h
#ifndef SCORE_H_
#define SCORE_H_
#include <string>
#include <iostream>
#include <iostream>
using std::string;
using std::ostream;
class Score
{
public:
Score(string name);
Score();
virtual ~Score();
void addPoints(int n);
string scoreGetName() const;
int getPoints() const;
void scoreSetName(string name);
bool operator>(const Score right) const;
private:
string _name;
int _points;
};
#endif
Note: You might want to look at the operator overloading FAQ.
Binary operators can either be members of their left-hand argument's class or free functions. (Some operators, like assignment, must be members.) Since the stream operators' left-hand argument is a stream, stream operators either have to be members of the stream class or free functions. The canonical way to implement operator<< for any type is this:
std::ostream& operator<<(std::ostream& os, const T& obj)
{
// stream obj's data into os
return os;
}
Note that it is not a member function. Also note that it takes the object to stream per const reference. That's because you don't want to copy the object in order to stream it and you don't want the streaming to alter it either.
Sometimes you want to stream objects whose internals are not accessible through their class' public interface, so the operator can't get at them. Then you have two choices: Either put a public member into the class which does the streaming
class T {
public:
void stream_to(std::ostream&) const {os << obj.data_;}
private:
int data_;
};
and call that from the operator:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
obj.stream_to(os);
return os;
}
or make the operator a friend
class T {
public:
friend std::ostream& operator<<(std::ostream&, const T&);
private:
int data_;
};
so that it can access the class' private parts:
inline std::ostream& operator<<(std::ostream& os, const T& obj)
{
os << obj.data_;
return os;
}
Let's say you wanted to write an operator overload for + so you could add two Score objects to each other, and another so you could add an int to a Score, and a third so you could add a Score to an int. The ones where a Score is the first parameter can be member functions of Score. But the one where an int is the first parameter can't become member functions of int, right? To help you with that, you're allowed to write them as free functions. That is what is happening with this << operator, you can't add a member function to ostream so you write a free function. That's what it means when you take away the Score:: part.
Now why does it have to be a friend? It doesn't. You're only calling public methods (getPoints and scoreGetName). You see lots of friend operators because they like to talk directly to the private variables. It's ok by me to do that, because they are written and maintained by the person maintaing the class. Just don't get the friend part muddled up with the member-function-vs-free-function part.
You're getting compilation errors when operator<< is a member function in the example because you're creating an operator<< that takes a Score as the first parameter (the object the method's being called on), and then giving it an extra parameter at the end.
When you're calling a binary operator that's declared as a member function, the left side of the expression is the object the method's being called on. e.g. a + b might works like this:
A a;
B b
a.operator+(b)
It's typically preferable to use non-member binary operators (and in some cases -- e.g. operator<<for ostream is the only way to do it. In that case, a + b might work like this:
A a;
B b
operator+(a, b);
Here's a full example showing both ways of doing it; main() will output '55' three times:
#include <iostream>
struct B
{
B(int b) : value(b) {}
int value;
};
struct A
{
A(int a) : value(a) {}
int value;
int operator+(const B& b)
{
return this->value + b.value;
}
};
int operator+(const A& a, const B& b)
{
return a.value + b.value;
}
int main(int argc, char** argv)
{
A a(22);
B b(33);
std::cout << a + b << std::endl;
std::cout << operator+(a, b) << std::endl;
std::cout << a.operator+(b) << std::endl;
return 0;
}