I need to use a virtual << operator. However, when I try to write:
virtual friend ostream & operator<<(ostream& os,const Advertising& add);
I get the compiler error
Error 1 error C2575: 'operator <<' :
only member functions and bases can be
virtual
How can I turn this operator virtual?
The problem with this setup is that the operator<< you defined above is a free function, which can't be virtual (it has no receiver object). In order to make the function virtual, it must be defined as a member of some class, which is problematic here because if you define operator<< as a member of a class then the operands will be in the wrong order:
class MyClass {
public:
virtual ostream& operator<< (ostream& out) const;
};
means that
MyClass myObject;
cout << myObject;
will not compile, but
MyClass myObject;
myObject << cout;
will be legal.
To fix this, you can apply the Fundamental Theorem of Software Engineering - any problem can be solved by adding another layer of indirection. Rather than making operator<< virtual, consider adding a new virtual function to the class that looks like this:
class MyClass {
public:
virtual void print(ostream& where) const;
};
Then, define operator<< as
ostream& operator<< (ostream& out, const MyClass& mc) {
mc.print(out);
return out;
}
This way, the operator<< free function has the right parameter order, but the behavior of operator<< can be customized in subclasses.
You define your operator << to call a virtual print method:
class Base
{
protected:
virtual void print(std::ostream& str) const = 0;
public:
friend std::ostream& operator<<(std::ostream& str, Base const& data)
{
data.print(str);
return str;
}
}
It looks like you really want to provide output functionality for a hierarchy of classes, and if so, you can provide a friend operator << that calls a virtual function.
class Parent
{
public:
friend std::ostream& operator<< (std::ostream& os, const Parent& p);
// ... other class stuff
protected:
virtual void printMyself(std::ostream& os) const
{
// do something if you must, or make this a pure virtual
}
};
std::ostream& operator<< (std::ostream& os, const Parent& p)
{
p.printMyself(os);
return os;
}
class Child : public Parent
{
// other class stuff...
protected:
virtual void printMyself(std::ostream os) const
{
// whatever you need to do
}
};
Also detailed in the C++ FAQ
Related
Suppose we have this scenario(maybe a little bit artificial)
class OStream
{
virtual void f1() = 0;
...
virtual void f10() = 0;
template<typename T>
OStream& operator<<(const T& t)
{
//doing something
}
};
class MyClass : public OStream
{
virtual void f1() override;
...
virtual void f10() override;
}
In another CPP file, there is another Foo class defined with a friend function like this
friend OStream& operator<<(OStream& ostream, Foo& obj)
{
//doing something with obj
}
Now consider a completely different file that contains such a snippet
...
MyClass obj; //suppose the constructor is defined
Foo foo; //there as well
obj << foo; // which operator is called???? I guess the second one
...
And what operator will be called if I overload OStream::operator<< inside MyClass(it is templated(thus non-virtual), thus I am just hiding the original one?
If I have an abstract class, let's call it "Vertebrate", it has a field std::string name; and it has a pure virtual method
virtual void print(std::ostream&) const noexcept = 0; which will be overridden in child classes and called in operator<<.
I get how polymorphism works, and how to implement the operator<< in inherited classes.
What I don't get:
I don't get this: how to implement an operator<< in that abstract class, that uses the virtual print function. Why this code does not work? My abstract class needs to have operator<<.
virtual void print(std::ostream&) const noexcept = 0;
std::ostream & operator<<(std::ostream & str, Member &obj)
{
return obj.print(str);
}
That is the abstract class code.
You are trying to return the result of print which is void, but operator<< should return std::ostream.
The following should work:
class Vertebrate
{
// ...
virtual void print(std::ostream&) const noexcept = 0;
};
std::ostream& operator<<(std::ostream& stream, Vertebrate& obj)
{
obj.print(stream);
return stream;
}
I have a basic abstract class Base.
class Base
{
protected:
string m_Name;
public:
virtual string Name() { return m_Name; }
virtual string Type() = 0;
virtual bool isEqual(Base* rhs) = 0 ;
//virtual ostream& operator<< (ostream& out) const;
};
I would like to overload the operator << to display objects that inherit from Base.
I cannot use a void print() function because these objects that inherit from Base also have some objects that can only be displayed by operator <<.
How can I overload the operator << ?
A common pattern is to provide a virtual print method, and use that in an ostream&<< operator:
class Base
{
public:
void print(std::ostream& o) const { /* do your stuff */ }
virtual ~Base() {}
};
std::ostream& operator<<(std::ostream& o, const Base& b)
{
b.print(o);
return o;
}
The idea is that each derived type implements print(ostream&) according to its needs.
Is this the only way of overloading the ostream& operator<< for a derived class without duplicating code for the base class? Are the casts not something to be avoided?
I don't see any other way, except to define some kind of function in the base class that will represent the data of the base class as something that std::operator<< could "eat up" (like a string?), doing the same thing for the derived class (calling the base class stream representation function within the derived class stream. rep. function of course).
What is the ideal solution to this problem?
#include <iostream>
class Base
{
private:
int b_;
public:
Base()
:
b_()
{};
Base (int b)
:
b_(b)
{};
friend std::ostream& operator<<(std::ostream& os, const Base& b);
};
std::ostream& operator<< (std::ostream& os, const Base& b)
{
os << b.b_;
return os;
}
class Derived
:
public Base
{
private:
int d_;
public:
Derived()
:
d_()
{};
Derived (int b, int d)
:
Base(b),
d_(d)
{};
friend std::ostream& operator<<(std::ostream& os, const Derived& b);
};
std::ostream& operator<< (std::ostream& os, const Derived& b)
{
os << static_cast<const Base&>(b) << " " << b.d_;
return os;
}
using namespace std;
int main(int argc, const char *argv[])
{
Base b(4);
cout << b << endl;
Derived d(4,5);
cout << d << endl;
return 0;
}
Well ... casting should be avoided if done in contexts where the result is not correctly defined, but casting into a base is always safe.
It is possible to avoid the explicit cast by considering that a derived reference decays into the base reference, so you can use an implicit conversion, like in this case:
std::ostream& operator<< (std::ostream& os, const Derived& b)
{
const Base& bs = b;
os << bs << " " << b.d_;
return os;
}
static_cast<const Base&>(b)
is safe and there is nothing incorrect, because every derived class object is also an Base class object and can be treated like one.
Casts are dangerous only when used in a reckless way, You must use casts where they are needed and in a correct manner, that is the very purpose of their provision by the language standard.
If you don't like the casts, you can have your operator call a writeTo function that is implemented using the template method pattern.
e.g.
class Base {
public:
std::ostream& writeTo(std::ostream& ostr) const { os << b_; return this->doWriteTo(os); }
private:
int b_;
virtual std::ostream& doWriteTo(std::ostream& ostr) const = 0; // pure virtual
};
class Derived {
private:
int d_;
virtual std::ostream& doWriteTo(std::ostream& ostr) const {return ostr << d_;}
};
std::ostream& operator<<(std::ostream& ostr, const Derived& d) {
return d.writeTo(ostr);
}
Actually, using this pattern, you can write operator<< once and for all for Base:
std::ostream& operator<<(std::ostream& ostr, const Base& b) {
return b.writeTo(ostr);
}
This pattern also elminates the need to make operator<< a friend.
You could change things around like this:
struct Base {
int b_;
void print(ostream &o) { o << b_; }
};
struct Derived : Base {
int d_;
void print(ostream &o) {
Base::print(o);
o << ' ' << d_;
}
};
ostream &operator<<(ostream &o, Base &b) {
b.print(o);
return o;
}
ostream &operator<<(ostream &o, Derived &d) {
d.print(o);
return o;
}
If Base had virtual functions (which in this example it doesn't), then print could be one of them, and you could get rid of the multiple overloads of operator<<.
I have the following classes in C++:
class Event {
//...
friend ofstream& operator<<(ofstream& ofs, Event& e);
};
class SSHDFailureEvent: public Event {
//...
friend ofstream& operator<<(ofstream& ofs, SSHDFailureEvent& e);
};
The code I want to execute is:
main() {
Event *e = new SSHDFailureEvent();
ofstream ofs("file");
ofs << *e;
}
This is a simplification, but what I want to do is write into a file several type of Events
in a file. However, instead of using the operator << of SSHDFailureEvent, it uses the operator << of Event. Is there any way to avoid this behavior?
Thanks
That would not work, as that would call operator<< for the base class.
You can define a virtual function print in base class and re-define it all derived class, and define operator<< only once as,
class Event {
virtual ofstream& print(ofstream & ofs) = 0 ; //pure virtual
friend ofstream& operator<<(ofstream& ofs, Event& e);
};
//define only once - no definition for derived classes!
ofstream& operator<<(ofstream& ofs, Event& e)
{
return e.print(ofs); //call the virtual function whose job is printing!
}
Try:
class Event
{
//...
friend ofstream& operator<<(ofstream& ofs, Event& e)
{
e.print(ofs);
return ofs;
}
virtual void print(std::ofstream& ofs)
{
ofs << "Event\n";
}
};
class SSHDFailureEvent: public Event
{
virtual void print(std::ofstream& ofs)
{
ofs << "SSHDFailureEvent\n";
}
};
The answers so far have the right idea but before you run ahead and implement it, two changes:
Use ostream not ofstream
The print function should be const.
Thus:
class Event
{
public:
virtual ~Event();
virtual std::ostream& printTo( std::ostream& ) const /*= 0*/;
// other public methods
};
/*inline*/ std::ostream& operator<<(std::ostream& os, const Event& event)
{
return event.printTo(os);
}
As long as print (or printTo) is public there is no need to make the stream operator overload a friend.
You have the option of having a default implementation or making the print method pure virtual.
You can also make print() a public non-virtual function that calls a protected or private virtual one, as is the case with all virtual functions.
I see two possibilities here:
Call an explicit print method on the class you are trying to print. For example implement
vritual print(std::ofstream& os);
in the base and the children.
Or -
Attempt to dynamically cast the base class to it's children.
SSHDFailureEvent* fe = dynamic_cast<SSHDFailureEvent*>(new Event());