overloading operator<< in derived classes

Jun 12, 2009 at 10:19pm
Hey everyone, my first post in here. I'm having some serious problem with a program I'm making. I want to overload the <<, using ostream, and I'm having problems with it in the derived classes I'm using.


This is my base class (I've only put the operations related to this problem, and I'll do the same with the next class):

class Pessoa
{
Pessoa(const Pessoa &);
Pessoa & operator=(const Pessoa&);
friend ostream & operator<<(ostream &, const Pessoa &);

}

Pessoa::Pessoa(const Pessoa & pessoa)
{
nome = pessoa.nome;
telemovel = pessoa.telemovel;
id = pessoa.id;

}



Pessoa & Pessoa::operator=(const Pessoa& pessoa)
{
id = pessoa.getId();
nome = pessoa.getNome();
telemovel = pessoa.getTelemovel();
return *this;
}

ostream & operator<<(ostream& os,const Pessoa& pessoa)
{
os << pessoa.getId() << " | " << pessoa.getNome() << " | " << pessoa.getTelemovel();
return os;
}

I've compiled this and it gave me no errors.

Now here's one of the derived classes:

class Utente: public Pessoa
{



public:

Utente(const Utente &);

Utente & operator=(const Utente &);
friend ostream & operator<<(ostream &, const Utente &);

};



Utente::Utente(const Utente &utent)
{
nome = utent.nome;
telemovel = utent.telemovel;
id = utent.id;
percentagem = utent.percentagem;
consulta_efect = utent.consulta_efect;
consulta_marc = utent.consulta_marc;
}


Utente & Utente::operator=( const Utente &utent)
{
Pessoa::operator=(utent);
percentagem = utent.percentagem;
consulta_efect = utent.consulta_efect;
consulta_marc = utent.consulta_marc;
return *this;
}



ostream & operator<<(ostream &os, const Utente &utent)
{
os << utent.id << " | " << utent.nome << " | " << utent.telemovel << " | " << utent.percentagem << " | " << utent.consulta_efect << " | " << utent.consulta_marc;
return os;

}

When I compile this class, it tells me there's a problem with ostream & operator<< and I get an enourmous wall of text. Does anyone have any idea how to solve this?

Jun 12, 2009 at 11:54pm
It appears you are attempting to have the derived class' operator<< output the base class members, which is possible, but only if the base class members are public or protected.

Probably the better way to write the derived class' operator<< is like this:

1
2
3
4
ostream& operator<<( ostream& os, const Utente& utent )
{
    return os << static_cast<const Pessoa&>( *this ) << /* derived class members */;
}


Unfortunately operator overloading and polymorphism combined don't exactly lend themselves to nice code; the cast is necessary to call the base class' operator<<.
Jun 13, 2009 at 12:45am
The base class member-atributes are protected and the member-functions are public.

The code you wrote is giving me this error: invalid use of "this" in non member function.

Any ideas how to solve this?

By the way, I only intend to output in the program itself the derived class members, but for that I need to output the base class members. At least that's what I think.

Thanks for your input!
Jun 13, 2009 at 1:40am
Oh, sorry,

static_cast<const Pessoa&>( utent )

Jun 13, 2009 at 2:19am
I still get an enormous wall of text, this is really stressing.
Jun 13, 2009 at 3:39am
Ok, can you post the error you are seeing?
Jun 13, 2009 at 4:03am
error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::
char_traits<char>](((std::basic_ostream<char, std::char_traits<char>
>&)((std::basic_ostream<char, std::char_traits<char> >*)((std::
basic_ostream<char, std::char_traits<char> >*)std::operator<< [with
_Traits = std::char_traits<char>](((std::basic_ostream<char, std::
char_traits<char> >&)((std::ostream*)operator<<(((std::ostream&)
((std::ostream*)os)), ((const Pessoa&)((const Pessoa*)((const Pessoa&)
(&((const Utente*)utent)->Utente::<anonymous>))))))), ((const char*)" |
")))->std::basic_ostream<_CharT, _Traits>::operator<< [with _CharT =
char, _Traits = std::char_traits<char>](utent->Utente::percentagem))),
((const char*)" | ")) << utent->Utente::consulta_efect’
Jun 13, 2009 at 4:19am
What is the type of percentagem?
Jun 13, 2009 at 4:28am
It's a float. consulta_efect and consulta_marc are vector<Consulta>.

I've just noticed something. Utente is dependent on Consulta, and Consulta is dependent on Utente. I've solved this cyclical dependency by writing a forward declaration in these two classes. But I wonder if this is the cause of the problem.
Jun 13, 2009 at 4:47am
Probably not.

Did you write an operator<< for vector<Consulta> and for Consulta?
Jun 13, 2009 at 5:00am
For Consulta yeah, but I didn't for vector<Consulta>. How am I supposed to do that?
Jun 13, 2009 at 5:30am
1
2
3
4
5
ostream& operator<<( ostream& os, const vector<Consulta>& v )
{
    // however you want this to appear
    return os;
}


I typically do (if you are familiar with the boost::lambda library)

1
2
   std::for_each( v.begin(), v.end(), os << '{' << boost::lambda::_1 << ',' );
   return os << '}';

Jun 13, 2009 at 10:27am
But I didn't create a seperate class for every vector<something> in my program. Is it necessary to create them?
Jun 13, 2009 at 2:28pm
Yes. ostream does not have an operator<< overload that takes any arbitary vector, so you have to write one.

EDIT: here's a solution that might suffice for your purpose:
1
2
3
4
5
6
template< typename T, typename Alloc >
ostream& operator<<( ostream& os, const vector<T,Alloc>& v )
{
    // code here
    return os;
}


And now every vector in your program is ostreamable.
Last edited on Jun 13, 2009 at 2:31pm
Jun 13, 2009 at 3:04pm
Where should I put that template?
Jun 14, 2009 at 3:22am
You'll need to put it in a header file that gets included by any .cpp file that you intend to output a vector<>.
Jun 14, 2009 at 10:44am
EDIT: Nevermind, I've got it working, thanks.
Last edited on Jun 14, 2009 at 9:16pm
Topic archived. No new replies allowed.