I'm trying to figure out how to attach a class with pure virtual <</>> operators to other classes for the purpose of saving/loading the application state.

So I started off with:

class IWriteable  
{
public:
	IWriteable(): pCls(NULL) {}
	IWriteable(void *p): pCls(p) {}
	virtual ostream& operator << (const void * &p) = 0;
	virtual istream& operator >> (const void * &p) = 0;

protected:
	void *pCls;

};

This probably would've worked fine, but then there's that annoying void pointer that I should "never use." But the idea here would be to initialize pCls with a pointer to the derived class and cast accordingly to access the derived class' members.

Since I should "never use" them. I switched over to a template implementation but now I come across an area that I'm unfamiliar with the templates. Normally I just add the function definitions underneath the template class declaration (as I always get errors if I try to put them in a .cpp file). But I can't really do that now.... at least I don't think I can as I'll get a circular reference going on between the header file of the derived class. Unless there's something I'm not doing right...... which is a decent possibility.

Template Implementation:

//Writeable.h
template <typename T> class IWriteable  
{
public:
	IWriteable() {}
	virtual ostream& operator << (const T &p) = 0;
	virtual istream& operator >> (const T &p) = 0;
};

//Order.h
class COrder : public IWriteable<COrder>
{
public:
	COrder() {::memset(this,0,sizeof(*this));}
	//Link to trades from OrderSlates

	int			iOrderNumber;
	time_t		tOpen;
	time_t		tClose;
	int			iOrderType;
	double		dLots;
	string		szSymbol;
	double		dOpenPrice;
	double		dSL;
	double		dTP;
	double		dClosePrice;
	double		dSlippage;
	double		dSwap;
	double		dCommission;
	double		dProfit;
};

ostream& IWriteable<COrder>::operator << (const COrder &p) {
}

ostream& IWriteable<COrder>::operator >> (const COrder &p) {
}

If I put in the ostream &os/istream &is parameters the compiler came back at me with "Too many parameters." I don't know if my choice was correct in the single parameter. But above gives me a bunch of errors (aside from no return type), function redefinitions (order.h(42) : error C2371: '>>' : redefinition; different basic types), pure virtual function can't be used (but I want this.... I'll explain), etc.

The goal here aside from just saving/loading is to:

  • Force me to implement the <</>> operators for different classes I want. My brain has become like swiss cheese so having the compiler tell me I forgot to implement these as a reminder is a quick way for me to fix it.
  • All the overrides will be better organized in the class browser control.
  • Easier to maintain.

I'm going to pursue the void pointer method for now just to get something working but I prefer to use templates if it's possible. Is it? Or does a better solution exist?

I have a basic stream question too that has been bugging me on and off for years. What I usually end up doing is not using streams (which is why I don't know too much about streams)

Is there anyway to use <</>> to write binary unformatted data to a stream? Some flag I haven't seen yet? Manipulator?...... I think my brain finally kicked in.... reinterpret_cast to char (w/i the operator overload) and write that to stream? But then the problem would be the functions don't have different declarations? (i.e. ostream& operator << (ostream& os, float) already exists :/ )

Or did I overlook something?

Thanks for your help.

Welcome nrobidoux,
I have try to answer the following question.

I'm trying to figure out how to attach a class with pure virtual <</>> operators to other classes for the purpose of saving/loading the application state.

Overload a << (insertor) method; it must be friend. Insertor operator method requires two arguments. An object is supposed to be at left of << operator.

cout << obj; // Yes
 obj << cout; // No

Here is code that demonstrate how to overload an insertor operator and print state of entire hierarchy of classes.

#include <iostream>

class Base {
 public:
   friend std::ostream& operator<< (std::ostream& refobj, const Base& b);
 protected:
   virtual void print(std::ostream& refobj) const = 0;
};

inline std::ostream& operator<< (std::ostream& refobj, const Base& b)
{
   b.print(refobj);
   return refobj;
 }

class Derived1 : public Base {
 public:
 protected:
   virtual void print(std::ostream& o) const
   {
       std::cout << "\nDerived1";
   }
};

class Derived2 : public Base {
 public:
 protected:
   virtual void print(std::ostream& o) const
   {
       std::cout << "\nDerived2";
   }
};
int main(){
 Derived1 a;
 Derived2 b;
 std::cout << a << " " << b;
 return 0;
}
Member Avatar for jencas
COrder() {::memset(this,0,sizeof(*this));}

I really hope that you know what you are doing here....

Works fine as long as no virtual functions are used in the current or base classes. Which was the case originally before I wanted to add this <</>> base class to it..... If any virtual pointers are present it sets the virtual pointer to 0 which results in disaster :)

Which would've been apparent pretty quickly if I ever got it to compile.

Thanks adatapost, works like a charm.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.