Problems overloading the << Operator - c++

I am trying to overload the << operator for my Currency class but I get this compiler error: C2143: syntax error : missing ';' before '&'
In my .h file I have:
friend ostream &operator << (ostream &, const Currency&);
And in my Currency.cpp file I have:
ostream &operator << (ostream &stream, const Currency &obj){
stream<<"$"<<obj.dollars<<"."<<obj.cents;
return stream;
}
Everything up until now worked fine, but choked once I put that in:
I have the following at the top of my .h file:
#ifndef CURRENCY_H
#define CURRENCY_H
#include<iostream>
#include<string>
#include<ostream>
#include<sstream>
class Currency; //forward delcaration
//Function prototypes for overloaded stream operators
ostream &operator << (ostream &, const Currency &);
I have no idea what I am doing wrong. Help would be great. Thanks

ostream is declared in namespace std and you are missing std:: identifier before it:
std::ostream &operator << (std::ostream &, const Currency &);
If you want to avoid std:: then after header file you can put using namespace statement:
...
#include<ostream>
using namespace std; // this is not desirable though in real world programming
ostream &operator << (ostream &, const Currency &);
Edit: using namespace <> is not recommended in real world programming at the file top. I have put that part just for FYI.

Related

is it possible to override the c++ operator<< for a struct in a header file?

I am trying to print out the fields in a struct by overriding operator<<. This works fine if I place the override in a cpp file, however I would like to have it in my header file.
However when I do, I get the error:
multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, test)'
Is it possible to have in the header file?
test.h
#ifndef TEST_H
#define TEST_H
struct test{
int a;
int b;
int c;
};
std::ostream& operator<< (std::ostream& o, const test& t){
o <<"{ " << t.a << " }" << endl;
return o;
}
#endif
As with any function, if you define it in a header, make it inline:
inline std::ostream& operator<< (std::ostream& o, const test& t)
^^^^^^
This relaxes the One Definition Rule, allowing a definition in any translation unit that includes the header.

C++ - ‘_itoa’ was not declared in this scope

In the UserProfile.h, I declared the class UserProfile...
#include <iostream>
#include <map>
#include <string>
using namespace std;
class UserProfile
{
...
}
then, I defined the function UserProfile() and operator<< in the UserProfile.cpp
#include "UserProfile.h"
#include <cstdlib>
inline UserProfile::UserProfile()
: _login("guest"), _user_level(Beginner),
_times_logged(1), _guesses(0), _correct_guesses(0)
{
static int id = 0;
char buffer[16];
_itoa(id++, buffer, 10);
_login += buffer;
}
...
ostream& operator<<(ostream &os, const UserProfile &rhs)
{
os << rhs.login() << ' '
<< rhs.level() << ' '
<< rhs.login_count() << ' '
<< rhs.guess_count() << ' '
<< rhs.guess_correct() << ' '
<< rhs.guess_average() << endl;
return os;
}
However, when I try to compile them, the g++ report error:
g++ UserProfile.cpp E44.cpp -o main
UserProfile.cpp: In constructor ‘UserProfile::UserProfile()’:
UserProfile.cpp:11:27: error: ‘_itoa’ was not declared in this scope
_itoa(id++, buffer, 10);
But I have included "cstdlib"... so strange...
Also, when I want to use << in my main cpp, the g++ report error too:
#include "UserProfile.h"
int main()
{
UserProfile anon;
cout << anon;
...
}
g++ report:
E44.cpp: In function ‘int main()’:
E44.cpp:6:10: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘UserProfile’)
cout << anon;
I am so confused... Did I do something wrong??
The correct name of the function is itoa not _itoa. However, it cannot be used in C++. cplusplus.com says:
This function is not defined in ANSI-C and is not part of C++, but is supported by some compilers.
Instead, use std::to_string or string streams.
As far as the compile time error regarding operator<< is concerned, that is because you define the operator in another translation unit than the one with the main function which will be compiled separately I guess and you don't declare it in the header file. In order for this to work you need to declare the overloaded operator, preferably in the same header file as the class' header file UserProfile.h.
ostream& operator<<(ostream &os, const UserProfile &rhs);
Moreover, you may want to make it a friend of your class to directly access fields and not using methods. That doesn't break encapsulation because you implement both the class and the overloaded operator.
class UserProfile
{
friend ostream& operator<<(ostream &os, const UserProfile &rhs);
};

Defining an overloaded outstream operator outside a class

Here is some simple code that I wrote. It simply copies an object and displays it data functions with an overloaded operator.
//Base
#include<iostream>
#include<istream>
#include<ostream>
using std::ostream;
using std::istream;
using namespace std;
class Sphere{
public:
Sphere(double Rad = 0.00, double Pi = 3.141592);
~Sphere();
Sphere(const Sphere& cSphere)
//overloaded output operator
friend ostream& operator<<(ostream& out, Sphere &fSphere);
//member function prototypes
double Volume();
double SurfaceArea();
double Circumference();
protected:
double dRad;
double dPi;
};
//defining the overloaded ostream operator
ostream& operator<<(ostream& out, Sphere& fSphere){
out << "Volume: " << fSphere.Volume() << '\n'
<< "Surface Area: " << fSphere.SurfaceArea() << '\n'
<< "Circumference: " << fSphere.Circumference() << endl;
return out;
}
The member functions are defined in a .cpp file. The problem is that when I compile this program I am told
there are multiple definitions of operator<<(ostream& out, Sphere& fSphere)
This is strange because the outstream operator is a non-member function so it should be able to be defined out of the class. Yet the program works well when I define this operator inside the class. Whats going on?
It seems you defined the operator in a header file and include this header in multiple cpp modules. or you include one cpp module with the function definition in other cpp module.
Usually the error mesage shows where a function is multiple defined. So reread all lines of the error message
Take into account that it would be better to declare the operator as
ostream& operator<<(ostream& out, const Sphere &fSphere);
Looks like the code you presented if the header file. And it contains the definition of operator<<, so any file including your header has its own copy of this definition, hence "multiple definitions" error. Add the keyword inline to your function, or move the function to .cpp file.

Where to put overload<< code?

I am trying to overload the stream operator <<, for a class Foo which has already a toString() function returning a string, with the following code:
std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
flux << foo.toString();
return flux;
}
In order to use it in a main.cppfile
My question is: Where to put that piece of code?
If I place it in the main.cpp, before its usage, it works well, but i may want to use it in other files.
If I place it in foo.cpp, I get a 'no such function' error:
src/main.cpp:77: error: no match for ‘operator<<’ in ‘std::cout << foo’
which make sense since the code is not included to the main.cpp file
If I place it in the foo.hclass header, outside class declaration, I get a 'multiple definition' error:
foo.o: In function `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Foo const&)':
foo.cpp:(.text+0x0): multiple definition of `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Matrix const&)'
bar.o:bar.cpp:(.text+0x0): first defined here
The foo.h header is indeed included in different classes/files, but there is a ifdef guard, so I don't understand this.
So How should I do?
There are multiple options:
Declare it in the header, after Foo, and define it in Foo.cpp.
//foo.h
class Foo
{};
std::ostream &operator<<( std::ostream &s, Foo const& foo );
//foo.cpp
#include "foo.h"
std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
Define it as a friend inside the class definition.
//Foo.h
class Foo
{
friend std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
};
Define it in the header, outside the class definition, and mark it as inline to prevent the multiple definition.
//Foo.h
class Foo
{
};
inline std::ostream &operator<<( std::ostream &s, Foo const& foo )
{
return s;
}
Put the prototype of the overload by the class declaration, the implementation thereof at the Foo implementation (or if you want it inline, put it at the Foo declaration).
So either:
// foo.h
#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
std::ostream& operator<< (std::ostream &, Foo const &);
#endif // FOO_H_ASDSADKJSLADJL
// foo.cpp
#include "foo.h"
....
std::ostream& operator<< (std::ostream &os, Foo const &) {
....
return os;
}
or
#ifndef FOO_H_ASDSADKJSLADJL
#define FOO_H_ASDSADKJSLADJL
class Foo {
};
inline std::ostream& operator<< (std::ostream &os, Foo const &) {
....
return os;
}
#endif // FOO_H_ASDSADKJSLADJL
Your error of the compiler not finding it was the lack of a prototype of your overload.
Put the declaration in the header file, and the definition in the cpp file.
That is, put
std::ostream &operator<<( std::ostream &flux, Foo const& foo );
in your header file, and put
std::ostream &operator<<( std::ostream &flux, Foo const& foo )
{
flux << foo.toString();
return flux;
}
in your cpp file.
This way, you can include the header file wherever you want, and things can use the function, but it will only be defined once, so you won't get the multiple definitions error.
Declare it in the header, where you declare Foo, define it in the source, where you define Foo methods.
As ususal with C and C++, you should
put the actual code into the appropriate .c / .cpp file - here I would recommend foo.cpp
put a predeclaration into the appropriate .h/.hpp header file, with an appropriate #ifdef guard for everything that is used from outside the main c/cpp file.
In some situations, you can use a #define macro, or an inline function. This should then be done in the header; there shouldn't be a multiple declaration error because of the inlining.
Technically you can do a lot of things. I recommend sticking to the best practise of defining the API in the header file, and putting the implementation into the code file. This is most extensible. The inline hack will work for this case, but if you at some later point decides to enhance the method and remove the inline, it will surprisingly break.
The header / code split is least likely to break.

template class, friend operator << overload

I'm trying to overload the "<<" operator for a template class. I've the definition of the class in a .h file and its implementation in a .cpp file.
/tmp/ccjJIJhO.o: In function `main':
main.cpp:(.text+0xad): undefined reference to `std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, FeatureVector<int>&)'
main.cpp:(.text+0xba): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, FeatureVector<int> const&)'
collect2: ld returned 1 exit status
The class definition:
common.h
#include <iostream>
using namespace std;
featurevector.h
#ifndef FEATURE_VECTOR_H
#define FEATURE_VECTOR_H
#include <common.h>
template < class FEAT_TYPE >
class FeatureVector;
template < class FEAT_TYPE >
istream & operator >> (istream &, FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
ostream & operator << (ostream &, const FeatureVector<FEAT_TYPE> &);
template < class FEAT_TYPE >
class FeatureVector{
public:
FeatureVector(int = 0);
...
friend istream & operator >> <>(istream &, FeatureVector<FEAT_TYPE> & );
friend ostream & operator << <>(ostream &, const FeatureVector<FEAT_TYPE> &);
...
~FeatureVector();
private:
int m_nDim;
FEAT_TYPE * m_pFeat;
};
#endif
featurevector.cpp
#include <featurevector.h>
...
template < class FEAT_TYPE >
istream & operator >> (istream & input, FeatureVector< FEAT_TYPE> & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
input >> refFeat.m_pFeat[d];
}
return (input);
}
template < class FEAT_TYPE >
ostream & operator << (ostream & output, const FeatureVector< FEAT_TYPE > & refFeat ){
int d;
for(d=0; d < refFeat.getDim(); d++){
output << refFeat.m_pFeat[d] << " ";
}
output << endl;
return (output);
}
...
#include "featurevector-impl.cpp"
featurevector-impl.cpp
template class FeatureVector<int>;
//template istream & operator >> <>(istream &, FeatureVector<int> &);
//template ostream & operator << <>(ostream &, const FeatureVector<int> &);
mylib.h
#ifndef MY_LIB_H
#define MY_LIB_H
#include <featurevector.h>
#endif
main.cpp
#include <mylib.h>
#include <common.h>
int main(){
FeatureVector<int> pFeat(10);
cin >> (pFeat);
cout << (pFeat);
return (0);
}
Makefile associated with "mylib"
INC=./inc
SRC=./src
LIB=./lib
OBJ=./obj
CC=g++
CFLAGS=-O3 -Wall
mylib: $(LIB)/mylib.a
echo "mylib was created!..."
$(LIB)/mylib.a: \
$(OBJ)/featurevector.o
ar csr $(LIB)/mylib.a \
$(OBJ)/featurevector.o
$(OBJ)/featurevector.o: $(SRC)/featurevector.cpp
$(CC) -c $(CFLAGS) $(SRC)/featurevector.cpp -I$(INC) \
-o $(OBJ)/featurevector.o
clean:
rm -rf $(LIB)/*.a
rm -rf $(OBJ)/*.o
Makefile for main.cpp (the main.cpp with its Makefile are under an "app" directory)
LIB=../lib
INC=../inc
OBJ=../obj
BIN=../bin
CC=g++
CFLAGS=-O3 -Wall
LFLAGS=-lmylib -lm
$#.cpp: $(LIB)/mylib.a $#.cpp
cd ..; make; cd app;
$(CC) $(CFLAGS) $#.cpp -o $(BIN)/$# -I$(INC) -L$(LIB) $(LFLAGS)
clean:
rm -rf $(BIN)/*
According to this, you have to make the function known as template in your class definition.
class.h
#include <iostream>
using std::ostream;
template <typename T>
class A {
public:
...
template <typename J> // <-- CAUTION!
friend ostream &operator<<(ostream &output, const A<J> &a);
};
class.cpp
#include "class.h"
...
template <typename T>
ostream &operator<<(ostream &output, const A<T> &a) {
// Your implementation
return output;
}
...
template ostream &operator<<(ostream &output, const A<int> &a);
template ostream &operator<<(ostream &output, const A<float> &a);
If the line template <typename J> is removed, the compilation error "underfined reference" comes.
See FAQ item 35.12 Why can't I separate the definition of my templates class from its declaration and put it inside a .cpp file?.
Your posted error code says that it is operator>> that is throwing an unresolved external error, not operator<<. In addition, your code won't compile because there is no convert constructor on myClass taking an int. So you have not posted the correct code.
But this works:
#include <iostream>
using namespace std;
template < class T >
class myClass;
template < class T >
ostream & operator << (ostream &, const myClass<T> &);
template < class T >
class myClass{
public:
myClass(int) {}
friend ostream & operator << <>(ostream &, const myClass<T> &);
private:
T m_Data;
};
template < class T >
ostream & operator << (ostream & out, const myClass<T> & refClass){
out << refClass.m_Data << endl;
return (out);
}
myClass<int>;
myClass<float>;
int main(int argc, char **argv){
myClass<int> test(5);
cout << test;
return 0;
}
Don't make it so complicated:
template<class FEAT_TYPE>
struct FeatureVector {
FeatureVector(int = 0);
friend std::istream& operator>>(std::istream &s, FeatureVector &x) {
for(int d = 0; d < x.getDim(); d++) {
s >> x.m_pFeat[d];
}
return s;
}
friend std::ostream& operator<<(std::ostream &s, FeatureVector const &x) {
// since you're terminating with " " rather than separating:
copy(x.m_pFeat, x.m_pFeat + x.getDim(), ostream_iterator<FEAT_TYPE>(s, " "));
s << endl;
return s;
}
//...
featurevector-impl.cpp is incorrect. Explicit template instantiations look like this:
template class FeatureVector<int>;
Since the operators aren't members, they must also be explicitly instantiated:
template istream & operator >> <>(istream &, FeatureVector<int> &);
I don't recommend splitting up your template definitions like this, though, unless you're really keen on micromanaging which specific classes will work with your template (which kind of goes against the spirit of using a template).