Connecting Tech Pros Worldwide Forums | Help | Site Map

ABC ostream & operator <<

Victor Irzak
Guest
 
Posts: n/a
#1: Jul 19 '05
Hello,

I have an ABC.
it supports:
ostream & operator <<

I also have a derived class that supports this operator.

How can I call operator << of the base class for derived object??? Is it
at all possible?


Here is an example. The line with // Error comment generates an error:
cannot create and instance of ABC.

TIA


#include <iostream>

using namespace::std;

class ABC {
protected:
int abc_member;
public:
virtual void onDraw() const = 0;
friend ostream & operator << (ostream &os, const ABC & o);
};

inline ostream & operator << (ostream &os, const ABC & o) {
os << "abc_member: " << o.abc_member;
return os;
}

class Derived : public ABC {
double der_member;
public:
Derived() {abc_member = 8; der_member=3.4f;}
virtual void onDraw() const {}
friend ostream & operator << (ostream &os, const Derived & o);
};

inline ostream & operator << (ostream &os, const Derived & o) {
os << "der_member: " << o.der_member;
return os;
}


int main () {
Derived * d = new Derived();
cout << *d << endl;
//cout << (ABC) *d << endl; // Error
return 0;
}



Stuart Golodetz
Guest
 
Posts: n/a
#2: Jul 19 '05

re: ABC ostream & operator <<


"Victor Irzak" <virzak@rogers.com> wrote in message
news:3F6C8FBB.41DF4503@rogers.com...[color=blue]
> Hello,
>
> I have an ABC.
> it supports:
> ostream & operator <<
>
> I also have a derived class that supports this operator.
>
> How can I call operator << of the base class for derived object??? Is it
> at all possible?
>
>
> Here is an example. The line with // Error comment generates an error:
> cannot create and instance of ABC.
>
> TIA
>
>
> #include <iostream>
>
> using namespace::std;
>
> class ABC {
> protected:
> int abc_member;
> public:
> virtual void onDraw() const = 0;
> friend ostream & operator << (ostream &os, const ABC & o);
> };
>
> inline ostream & operator << (ostream &os, const ABC & o) {
> os << "abc_member: " << o.abc_member;
> return os;
> }
>
> class Derived : public ABC {
> double der_member;
> public:
> Derived() {abc_member = 8; der_member=3.4f;}
> virtual void onDraw() const {}
> friend ostream & operator << (ostream &os, const Derived & o);
> };
>
> inline ostream & operator << (ostream &os, const Derived & o) {
> os << "der_member: " << o.der_member;
> return os;
> }
>
>
> int main () {
> Derived * d = new Derived();
> cout << *d << endl;
> //cout << (ABC) *d << endl; // Error
> return 0;
> }[/color]

#include <iostream>
// Prefer not to write "using namespace std;", either qualify everything
explicitly with std::, or write *local* using declarations (or directives,
if necessary).
// Actually, the reason I changed this was because VC++ was (wrongly)
refusing to compile it because the friend declaration wasn't recognised
properly.

class ABC
{
protected:
int abc_member;
public:
virtual void onDraw() const = 0;

friend std::ostream& operator<<(std::ostream& os, const ABC& o);
};

inline std::ostream& operator<<(std::ostream& os, const ABC& o)
{
os << "abc_member: " << o.abc_member;
return os;
}

class Derived : public ABC
{
private:
double der_member;
public:
Derived()
: der_member(3.4f) // prefer initialisation to assignment
{
abc_member = 8; // but we can't here, since abc_member is a
member of ABC rather than Derived
}

virtual void onDraw() const {}

friend std::ostream& operator<<(std::ostream& os, const Derived& o);
};

inline std::ostream& operator<<(std::ostream& os, const Derived& o)
{
os << "der_member: " << o.der_member;
return os;
}


int main()
{
Derived *d = new Derived; // you didn't need the brackets after
Derived
// Prefer '\n' to std::endl unless you intend to deliberately flush the
stream. There is non-negligible overhead involved in pointless flushing.
std::cout << *d << '\n';
std::cout << *((ABC*)d) << '\n'; // C-style cast
(easier to type)
std::cout << *(static_cast<ABC*>(d)) << '\n'; // C++-style cast
(easier to search for, among other advantages)
delete d;

return 0;
}

You were trying to cast the object when you should have just cast the
pointer.

HTH,

Stuart.


Victor Irzak
Guest
 
Posts: n/a
#3: Jul 19 '05

re: ABC ostream & operator <<


Yes, that helps.

Thanks for extra comments too!

Victor

Stuart Golodetz wrote:
[color=blue]
> "Victor Irzak" <virzak@rogers.com> wrote in message
> news:3F6C8FBB.41DF4503@rogers.com...[color=green]
> > Hello,
> >
> > I have an ABC.
> > it supports:
> > ostream & operator <<
> >
> > I also have a derived class that supports this operator.
> >
> > How can I call operator << of the base class for derived object??? Is it
> > at all possible?
> >
> >
> > Here is an example. The line with // Error comment generates an error:
> > cannot create and instance of ABC.
> >
> > TIA
> >
> >
> > #include <iostream>
> >
> > using namespace::std;
> >
> > class ABC {
> > protected:
> > int abc_member;
> > public:
> > virtual void onDraw() const = 0;
> > friend ostream & operator << (ostream &os, const ABC & o);
> > };
> >
> > inline ostream & operator << (ostream &os, const ABC & o) {
> > os << "abc_member: " << o.abc_member;
> > return os;
> > }
> >
> > class Derived : public ABC {
> > double der_member;
> > public:
> > Derived() {abc_member = 8; der_member=3.4f;}
> > virtual void onDraw() const {}
> > friend ostream & operator << (ostream &os, const Derived & o);
> > };
> >
> > inline ostream & operator << (ostream &os, const Derived & o) {
> > os << "der_member: " << o.der_member;
> > return os;
> > }
> >
> >
> > int main () {
> > Derived * d = new Derived();
> > cout << *d << endl;
> > //cout << (ABC) *d << endl; // Error
> > return 0;
> > }[/color]
>
> #include <iostream>
> // Prefer not to write "using namespace std;", either qualify everything
> explicitly with std::, or write *local* using declarations (or directives,
> if necessary).
> // Actually, the reason I changed this was because VC++ was (wrongly)
> refusing to compile it because the friend declaration wasn't recognised
> properly.
>
> class ABC
> {
> protected:
> int abc_member;
> public:
> virtual void onDraw() const = 0;
>
> friend std::ostream& operator<<(std::ostream& os, const ABC& o);
> };
>
> inline std::ostream& operator<<(std::ostream& os, const ABC& o)
> {
> os << "abc_member: " << o.abc_member;
> return os;
> }
>
> class Derived : public ABC
> {
> private:
> double der_member;
> public:
> Derived()
> : der_member(3.4f) // prefer initialisation to assignment
> {
> abc_member = 8; // but we can't here, since abc_member is a
> member of ABC rather than Derived
> }
>
> virtual void onDraw() const {}
>
> friend std::ostream& operator<<(std::ostream& os, const Derived& o);
> };
>
> inline std::ostream& operator<<(std::ostream& os, const Derived& o)
> {
> os << "der_member: " << o.der_member;
> return os;
> }
>
> int main()
> {
> Derived *d = new Derived; // you didn't need the brackets after
> Derived
> // Prefer '\n' to std::endl unless you intend to deliberately flush the
> stream. There is non-negligible overhead involved in pointless flushing.
> std::cout << *d << '\n';
> std::cout << *((ABC*)d) << '\n'; // C-style cast
> (easier to type)
> std::cout << *(static_cast<ABC*>(d)) << '\n'; // C++-style cast
> (easier to search for, among other advantages)
> delete d;
>
> return 0;
> }
>
> You were trying to cast the object when you should have just cast the
> pointer.
>
> HTH,
>
> Stuart.[/color]

Jerry Coffin
Guest
 
Posts: n/a
#4: Jul 19 '05

re: ABC ostream & operator <<


In article <3F6C8FBB.41DF4503@rogers.com>, virzak@rogers.com says...[color=blue]
> Hello,
>
> I have an ABC.
> it supports:
> ostream & operator <<
>
> I also have a derived class that supports this operator.
>
> How can I call operator << of the base class for derived object??? Is it
> at all possible?[/color]

IMO, it's better to avoid this as a rule. Instead, I'd use vaguely
along these lines:

#include <iostream>

class base {
int base_member;

protected:
virtual std::ostream &write(std::ostream &os) const {
return os << base_member << "\n";
}

// This only looks like a member function. It's really global.
friend std::ostream &operator<<(std::ostream &os, base const &b) {
return b.write(os);
}
public:
base(int init = 0) : base_member(init) { }
};

class derived : public base {
int derived_member;

virtual std::ostream &write(std::ostream &os) const {
base::write(os);
return os << derived_member << "\n";
}
public:
derived(int b_init, int d_init) : base(b_init), derived_member
(d_init) { }
};

#ifdef TEST

int main() {

base &b = *(new derived(0, 1));

std::cout << b;
return 0;
}

#endif

The friend operator<< can't be virtual itself, but because it calls a
virtual function, it invokes either base::write or derived::write,
depending on the type that's actually passed to it. If it was a derived
object, that explicitly calls the base::write to handle whatever the
base needs to do, then it writes out its own members.

At last IMO, the client code is NOT the place to deal with things like
this -- one of the fundamental points of object orientation is that the
object should hide details of its implementation, so this should really
be handled by the object itself (as above) rather than in client code
(as you were trying to do it). Of course, there are a few exceptions to
this kind of rule -- just for an obvious one, it might be reasonable to
print out some things during debugging that you won't under normal
circumstances, and it's often perfectly reasonable for the debugging
and/or testing code to know more about the object than the world at
large is supposed to.

--
Later,
Jerry.

The universe is a figment of its own imagination.
Closed Thread