I am attempting to override the << operator for a class. The purpose is basically to implement a toString() like behavior for my class, so that sending it to cout will produce useful output. Using a dummy example, I have the code below. When I attempt to compile, I get the foollowing error:
$ g++ main.cpp Rectangle.cpp
/tmp/ccWs2n6V.o: In function `operator<<(std::basic_ostream<char, std::char_traits<char> >&, CRectangle const&)':
Rectangle.cpp:(.text+0x0): multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, CRectangle const&)'
/tmp/ccLU2LLE.o:main.cpp:(.text+0x0): first defined here
I can't figure out why this is happening. my code is below:
Rectangle.h:
#include <iostream>
using namespace std;
class CRectangle {
private:
int x, y;
friend ostream& operator<<(ostream& out, const CRectangle& r);
public:
void set_values (int,int);
int area ();
};
ostream& operator<<(ostream& out, const CRectangle& r){
return out << "Rectangle: " << r.x << ", " << r.y;
}
Rectangle.cpp:
#include "Rectangle.h"
using namespace std;
int CRectangle::area (){
return x*y;
}
void CRectangle::set_values (int a, int b) {
x = a;
y = b;
}
main.cpp:
#include <iostream>
#include "Rectangle.h"
using namespace std;
int main () {
CRectangle rect;
rect.set_values (3,4);
cout << "area: " << rect.area();
return 0;
}
You're breaking the one definition rule. A quick-fix is:
inline ostream& operator<<(ostream& out, const CRectangle& r){
return out << "Rectangle: " << r.x << ", " << r.y;
}
Others are:
declaring the operator in the header file and moving the implementation to Rectangle.cpp file.
define the operator inside the class definition.
.
class CRectangle {
private:
int x, y;
public:
void set_values (int,int);
int area ();
friend ostream& operator<<(ostream& out, const CRectangle& r){
return out << "Rectangle: " << r.x << ", " << r.y;
}
};
Bonus:
use include guards
remove the using namespace std; from the header.
You are putting the definition of a function in a .h file, which means that it will appear in every translation unit, violating the One Definition Rule (=> you defined operator<< in every object module, so the linker doesn't know which is "the right one").
You can either:
write just the declaration of your operator (i.e. its prototype) in the .h file and move its definition to rectangle.cpp
make operator<< inline - inline functions are allowed to be defined more than once, as long as all the definitions are identical.
(Also, you should use header guards in your includes.)
Related
I'm trying to overload the << operator for one of my classes, but the linker keeps failing to find the overload. Been searching online for anything I've missed on how to declare and implement the operator overload but nothing seems to stand out to me. Any ideas how I can fix this?
Undefined symbols for architecture x86_64:
"memath::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, memath::Vector3 const&)", referenced from:
_main in mecli.cxx.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
vector3.h
#include <string>
#include <iostream>
namespace memath {
class Vector3 {
public:
double x;
double y;
double z;
Vector3();
std::string to_string() const;
friend std::ostream& operator<<(std::ostream &strm, const Vector3 &a);
};
};
vector3.cxx
#include <string>
#include <iostream>
#include <sstream>
#include "vector3.h"
using namespace memath;
Vector3::Vector3() : Vector3(0, 0, 0) {}
std::string Vector3::to_string() const {
std::ostringstream r;
r << "Vector3" << "(" << this->x << "," << this->y << "," << this->z << ")";
return r.str();
}
std::ostream& operator<<(std::ostream &strm, const Vector3 &a) {
strm << a.to_string();
return strm;
}
mecli.cxx
#include <iostream>
#include <cstdlib>
#include <string>
#include "vector3.h"
int main(int argc, char** argv) {
memath::Vector3 vec1;
std::cout << vec1 << std::endl;
}
because Vector3 is in namespace memath the friend declaration declares memath::operator<<, but you then define ::operator<<. So just make the definition match the declaration:
std::ostream& memath::operator<<(std::ostream &strm, const Vector3 &a) {
// ^~~~~~~~
Follow up question, why doesn't the using namespace memath; seem to matter at the top of the file in this case and exclude this operator overload in particular?
It isn't particular to this operator. Actually is not particular to operators. You get the same behavior with function. And it's not particular to friend declarations.
So let's see this on a simpler example:
namespace ns
{
struct X
{
int foo(int); // => ::ns::X::foo
};
int bar(int); // => ::ns::bar
}
using namespace ns;
int X::foo(int a) { return a + 1; } // (1) => ::ns::X::foo
int bar(int a) { return a * 2; } // (2) => ::bar
Just like in your example, foo works as you expect, but bar is ambiguous, just like your operator<<. So what's the difference between the two? Here's a simplified explanation:
(1): this is the definition of the qualified name foo. X:: is what makes it qualified. So foo is searched within X. But what is X? X is an unqualified name-id. So now an unqualified lookup is performed for X. This means X is searched in the current namespace (global) and in all namespaces brought in by the using directives. In this case X is found only in namespace ns. So X::foo is resolved to ns::X::foo which makes it the declaration of the method foo of the class ns::X.
(2) this is the definition of the unqualified name bar. Since bar is unqualified this is interpreted as the declaration of the name bar in the current namespace (the global namespace). Because bar is a new name being declared a lookup is not performed. So bar is the declaration of ::bar.
Please keep in mind this is a simplified explanation.
Just got into C++ and I have a quick question.
After compiling with
g++ *.cpp -o output
I receive this error:
error: 'ostream' in 'class Dollar' does not name a type
These are my three files:
main.cpp
#include <iostream>
#include "Currency.h"
#include "Dollar.h"
using namespace std;
int main(void) {
Currency *cp = new Dollar;
// I want this to print "printed in Dollar in overloaded << operator"
cout << cp;
return 0;
}
Dollar.cpp
#include <iostream>
#include "Dollar.h"
using namespace std;
void Dollar::show() {
cout << "printed in Dollar";
}
ostream & operator << (ostream &out, const Dollar &d) {
out << "printed in Dollar in overloaded << operator";
}
Dollar.h
#include "Currency.h"
#ifndef DOLLAR_H
#define DOLLAR_H
class Dollar: public Currency {
public:
void show();
};
ostream & operator << (ostream &out, const Dollar &d);
#endif
Thank you for your time, and everything helps!
You have a number of errors in the code.
You heavily use using namespace std. This is a bad practice. In particular, this led to the error you faced: you don't have using namespace std in Dollar.h, thus the compiler has no idea what ostream means. Either put using namespace std in Dollar.h too, or better just stop using it and specify the std namespace directly, as in std::ostream.
You use std::ostream in your headers, but you don't include the corresponding standard library header <ostream> in them (<ostream> contains the definition of std::ostream class; for the full I/O library include <iostream>). A really good practice is to include all the dependencies of the header in the header itself, so that it is self-contained and can be safely included anywhere.
You are implementing a stream output operator with signature std::ostream & operator << (std::ostream &, Dollar const &), which is perfectly valid. However, you call it for a pointer to type Dollar. You should rather call it with the object itself, not the pointer, so you should dereference the pointer: std::cout << *cp;.
You implemented the output operator for the Dollar class, but use it for a variable of type Currency: this won't work. There is a way to do this - there do exist virtual methods for this exact reason. However, in this case the operator is a free function, thus it cannot be virtual. So, you should probably add a virtual print method to your Currency class, implement it in Dollar, and call it from output operator:
#include <iostream>
class Currency {
public:
virtual void print (std::ostream &) const = 0;
};
class Dollar : public Currency {
void print (std::ostream & out) const override {
out << "A dollar";
}
};
std::ostream & operator << (std::ostream & out, Currency const & c) {
c.print(out);
return out;
}
int main(/* void is redundant here */) {
Currency *cp = new Dollar;
std::cout << *cp;
// return 0 is redundant in main
}
You need to #include <iostream> within Dollar.h so that your std::ostream & operator is resolved by the compiler.
I got an error, when I am trying to overload an operator.
My header file:
#include<iostream>
#include<string>
using namespace std;
#ifndef HALLGATO_H
#define HALLGATO_H
class Hallgato {
private:
char* nev;
char* EHA;
int h_azon;
unsigned int kepesseg;
public:
friend ostream& operator<<(ostream& output, const Hallgato& H);
};
#endif
My cpp file:
#include<iostream>
#include "Hallgato.h"
using namespace std;
ostream& Hallgato::operator<<(ostream& output, const Hallgato& H) {
output << "Nev: " << H.nev << " EHA: " << H.EHA << " Azonosito: " << H.h_azon << " Kepesseg: " << H.kepesseg << endl;
return output;
}
};
In my .cpp file, when I want to define the overloaded operator <<, I got an error. Why?
The operator is not a member of the class, it is a friend so
ostream& Hallgato::operator<<(ostream& output, const Hallgato& H) {
should be
ostream& operator<<(ostream& output, const Hallgato& H) {
also to be able to use the operator from other files you should add a prototype into the header file.
The header file would become this
hallgato.h
#ifndef HALLGATO_H
#define HALLGATO_H
#include<iostream>
#include<string>
class Hallgato {
private:
char* nev;
char* EHA;
int h_azon;
unsigned int kepesseg;
public:
friend std::ostream& operator<<(std::ostream& output, const Hallgato& H);
};
std::ostream& operator<<(std::ostream& output, const Hallgato& H);
#endif /* End of HALLGATO_H */
Somewhere in a ".cpp" file you would implement the operator function, you can also do it in the header file but then you would have to recompile often with some compilers.
hallgato.cpp
#include "hallgato.h"
std::ostream& operator<<(std::ostream& output, const Hallgato& H)
{
/* Some operator logic here */
}
NOTE:
When you modify header files, many compilers usually do not re-include them in your .cpp files. This is done to avoid unnecessary recompilation. To force a re-include, you have to make some modifications(delete empty line) to the source files which include those headers or force recompilation in your compiler/IDE.
In header file you declared friend method for class
friend ostream& operator<<(ostream& output, const Hallgato& H);
this method shoud be defined (in cpp) without Hallgato::
ostream& operator<<(ostream& output, const Hallgato& H)
because this method is not part of Hallgato class.
Update: I made Sergii's changes below, but now I get the error: undefined reference to `cs202::operator<<(std::basic_ostream >&, cs202::Rational const&)'. Any ideas how to fix this? Thanks
I would appreciate help figuring out why I am getting this error:
"error: 'output' is not a member of namespace 'cs202'"
I have a class called Rational as follows:
#ifndef RATIONAL_H
#define RATIONAL_H
namespace cs202{
class Rational
{
private:
int m_numerator;
int m_denominator;
public:
Rational(int nNumerator = 0, int nDenominator = 1) {
m_numerator = nNumerator;
m_denominator = nDenominator;
}
int getNumerator(){return m_numerator;}
int getDenominator(){return m_denominator;}
friend std::ostream& operator<<(std::ostream& output, const Rational& cRational);
};
}
#endif
The implementation file for the friend function which overrides the << operator looks like this:
#include "rational.h"
namespace cs202{
friend std::ostream& operator<<(std::ostream& output, const Rational& cRational)
{
output << cRational.m_numerator << "/" << cRational.m_denominator;
return output;
}
}
Finally, Main looks like this:
#include <iostream>
#include "rational.h"
using namespace std;
using namespace cs202;
int main()
{
Rational fraction1(1, 4);
cs202::output << fraction1 << endl;
return 0;
}
I have tried using cout instead of cs202:output, I have tried with and without the namespace cs202 (which is a requirement of the assignment), and I have tried making the operator overload function a member function of the class rather than a friend function to no avail.
What am I missing? Thanks
I suppose you want it out to standard output (to console)
int main()
{
Rational fraction1(1, 4);
std::cout << fraction1 << endl;
return 0;
}
Also you do not need friend here. "Friend" keyword is used only in a class
#include "rational.h"
namespace cs202{
std::ostream& operator<<(std::ostream& output, const Rational& cRational)
{
output << cRational.m_numerator << "/" << cRational.m_denominator;
return output;
}
}
Thanks, I figured it out. I had to change the placement of the {} for the namespace.
I get this when i try to compile:
../Monster.h:26:9: error: ‘int ProjectIV::Monster::con’ is private
`int con;`
^
../Monster.cpp:17:39: error: within this context
cout << "Constitution: " << monster.con << endl;
^
make: * [Monster.o] Error 1
From what I understand making operator<< a friend should allow it to access int con. What am I not seeing.
Monster.h:
#ifndef MONSTER_H_
#define MONSTER_H_
#include <iostream>
using std::cout;
using std::endl;
using std::ostream;
#include <string>
using std::string;
namespace ProjectIV
{
class Monster
{
friend ostream &operator<< (ostream &out, const Monster &monster);
public:
Monster(int con);
private:
int con;
};
} /* namespace ProjectIV */
#endif /* MONSTER_H_ */
Monster.cpp:
#include "Monster.h"
ostream &operator<< (ostream &out, const ProjectIV::Monster &monster)
{
cout << "Constitution: " << monster.con << endl;
return out;
}
ProjectIV::Monster::Monster(int con): con(con)
{}
main.cpp:
#include "Monster.h"
using namespace ProjectIV;
int main()
{
Monster Gojira(140);
cout << Gojira << endl;
return 0;
}
This:
ostream& operator<<(ostream& out, const ProjectIV::Monster& monster)
should be:
ostream& ProjectIV::operator<<(ostream& out, const ProjectIV::Monster& monster)
Here your not working example, and here is the working one.
Also, as per AndreyT's comment, you should add a function declaration before the friend declaration:
namespace ProjectIV {
class Monster {
friend ostream& operator<<(ostream& out, const Monster& monster);
public:
Monster(int con);
private:
int con;
};
ostream& operator<<(ostream& out, const Monster& monster);
// ^^^ this
}
There are two problems with your code.
Firstly, the friend declaration inside Monster class refers to ProjectIV::operator << function. It is ProjectIV::operator << that will become the friend of Monster. What you defined in your Monster.cpp file is actually a ::operator <<. This is a completely different function that is not a friend of Monster. This is why you get the error.
So, you need to decide what function you want to make a friend - the one in global namespace or the one in ProjectIV namespace - and act accordingly.
If you want to make your operator << a member of ProjectIV namespace, you run into the second problem. Friend declarations refer to member of enclosing namespace, but they don't introduce the corresponding declarations into the enclosing namespace. It is still your responsibility to add a declaration for operator << in ProjectIV
namespace ProjectIV
{
class Monster
{
friend ostream &operator<< (ostream &out, const Monster &monster);
public:
Monster(int con);
private:
int con;
};
ostream &operator<< (ostream &out, const Monster &monster);
} /* namespace ProjectIV */
and then later define it as a member of ProjectIV
ostream &ProjectIV::operator<< (ostream &out, const ProjectIV::Monster &monster)
{
cout << "Constitution: " << monster.con << endl;
return out;
}