I have a class IDocument which serve as a interface for some classes. It has some abstracts methods (virtual ... = 0).
I would like to do such all subclasses also have to implement an operator for serialization:
In addition to the overloaded stream operators documented here, any Qt classes that you might want to serialize to a QDataStream will have appropriate stream operators declared as non-member of the class:
I'm not even sure how I would make an abstract operator, but how do I define it nonmember?
A non-member operator is a free function, pretty much like any other free function. For QDataStream, on operator<< would look like:
QDataStream& operator<<(QDataStream& ds, SomeType const& obj)
{
// do stuff to write obj to the stream
return ds;
}
In your case, you could implement your serialization like this (this is just one way of doing it, there are others):
#include <QtCore>
class Base {
public:
Base() {};
virtual ~Base() {};
public:
// This must be overriden by descendants to do
// the actual serialization I/O
virtual void serialize(QDataStream&) const = 0;
};
class Derived: public Base {
QString member;
public:
Derived(QString const& str): member(str) {};
public:
// Do all the necessary serialization for Derived in here
void serialize(QDataStream& ds) const {
ds << member;
}
};
// This is the non-member operator<< function, valid for Base
// and its derived types, that takes advantage of the virtual
// serialize function.
QDataStream& operator<<(QDataStream& ds, Base const& b)
{
b.serialize(ds);
return ds;
}
int main()
{
Derived d("hello");
QFile file("file.out");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
out << d;
return 0;
}
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?
I have a user-defined class, say, MyClass. Suppose its definition is as follows:
class MyClass
{
int a;
int *b;
Base *c;
};
where I have
class Base
{
int base_data;
public:
Base(int) { //implementation }
virtual void some_func() = 0;
}
and
class Derived1 : public Base
{
int derived_1;
public:
Derived1(int) { //implementation }
virtual void some_func() { //implementation }
}
and
class Derived2 : public Base
{
int derived_2;
public:
Derived2(int) { //implementation }
virtual void some_func() { //implementation }
}
I would like to send an object of this class to a QTcpsocket. As per this answer, I could use a QDataStream, and with the help of this, I have implemented as follows:
friend QDataStream& operator<<(QDataStream&, const MyClass&);
friend QDataStream& operator>>(QDataStream&, MyClass&);
in the class declaration, and am considering defining it as:
QDataStream& operator<<(QDataStream &stream, const MyClass &obj)
{
stream << obj.a;
stream << obj.(*b);
stream << obj.(*Base); // assume QDataStream has been overloaded for Base already
}
As I need to send the data, I am dereferencing the pointers and sending the data it points to.
Is this the correct way to do this?
If I do send it this way, I am not able to understand how I can recreate the object at the receiving end. I am considering:
QDataStream& operator<<(QDataStream &stream, MyClass &obj)
{
stream >> obj.a;
b = new int;
stream >> obj.(*b);
Base = new //what?
stream >> obj.(*Base); // assume QDataStream has been overloaded for Base already
}
For an int pointer, I can create a new int and assign the incoming value to it. But what about a pointer of type Base? I don't know if it is of type Derived1 or Derived2.
How do I handle this?
Is there any other way to send a class object, if there is no solution here?
Thank you.
I have an interface that boils down to
class interface
{
protected:
virtual void write(std::string const &) = 0;
};
And derived classes like
class derived : public interface
{
protected:
void write(std::string const & buf)
{
std::cout << buf << std::endl;
}
};
In my application, these objects are passed around as smart pointers, i.e. std::shared_ptr<derived>. I hoped I could overload the << operator, but only for smart pointer of derivatives of my interface. I tried this:
class interface
{
/* ... */
private:
template <typename Derived> friend typename std::enable_if<
std::is_base_of<interface, Derived>::value,
std::shared_ptr<Derived>
>::type & operator<<(std::shared_ptr<Derived> & lhs,
std::string const & rhs)
{
lhs->write(rhs);
return lhs;
}
};
But when I try std::shared_ptr<derived> sp; sp << "test";, the compiler complains that virtual void derived::write(const string&) is protected within this context (this context is my friend function).
Is there a way to achieve this without redundantly writing a stream operator for every derived class?
Why not simply define your operator as:
friend std::shared_ptr<interface> &operator<<(std::shared_ptr<interface> & lhs, std::string const & rhs);
and pass your objects as std::shared_ptr<interface>?
I have a number of classes that represent various computer components, each of which have an overloaded << operator declared as follows:
friend ostream& operator << (ostream& os, const MotherBoard& mb);
Each returns an ostream object with a unique stream describing that component, some of which are composed of other components. I decided to create a base class called Component in order to generate a unique id as well as some other functions that all the components will publicly derive. Of course, the overloaded << operator doesn't work with pointers to Component objects.
I was wondering how I would effect something like a pure virtual function that will be overwritten by each derived class's << operator so I could do something like:
Component* mobo = new MotherBoard();
cout << *mobo << endl;
delete mobo;
Also related to: overloading << operators and inherited classes
Maybe something like this:
#include <iostream>
class Component
{
public:
// Constructor, destructor and other stuff
virtual std::ostream &output(std::ostream &os) const
{ os << "Generic component\n"; return os; }
};
class MotherBoard : public Component
{
public:
// Constructor, destructor and other stuff
virtual std::ostream &output(std::ostream &os) const
{ os << "Motherboard\n"; return os; }
};
std::ostream &operator<<(std::ostream &os, const Component &component)
{
return component.output(os);
}
int main()
{
MotherBoard mb;
Component &component = mb;
std::cout << component;
}
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());