问题
I have an abstract base class for a pointAccumulator. This abstract base will be filled out with methods such as a function that returns mean of all the points. An example of these two classes is shown below:
class lala {
public:
virtual someFunctions = 0;
virtual bool isEmpty() = 0;
};
class lalaLower : public lala {
public:
lalaLower(){}
~lalaLower(){}
someFunctions
template<class Archive> void serialize(Archive & ar, const unsigned int version) {
ar & heights_;
}
protected:
std::deque<double> heights_;
};
As you can see in the code I would also like to use boost serialization in to save these types. Now using a factory pattern i believe that you call the pointAccumulator types like this:
lala *a1 = new lalaLower();
My problem is that the templated serialize method will not be accessible if I call it this way. Also I cannot have the templated class in the abstract class as this is not allowed by c++. Is there a way to get around this?
Edit:
I have considered the non-intrusive method for serialization but that requires heights_ to be public which is not ideal, nor is it good programming style. I thought potentially a method using friend classes or functions could penetrate the class with access to the variables while still keeping the base class abstract? can anyone explain how this would work?
回答1:
I think using friend classes or functions is a good solution, you could add new class like Serializor
here is a example of friend function
class Serializor;
class meanAccumulator : public pointAccumulator
{
public:
meanAccumulator(){}
~meanAccumulator(){}
double getHeight();
void addHeight(double Height);
void setHeight(double Height);
bool isEmpty(){ return heights_.empty(); }
protected: std::deque<double> heights_;
friend int Serializor::Func1( Serializor& );
};
refer to http://msdn.microsoft.com/en-us/library/ahhw8bzz.aspx
回答2:
I believe you cannot do it without wrapping Archive
type parameter into polymorphic hierarchy this way or another.
It seems though that Boost.Serialization
does it for you.
回答3:
As you may know that template
s and virtual
methods don't go hand in hand.
I would suggest to remove the meanAccumulator::serialize()
method and add into class pointAccumulator
body and call the virtual
functions inside wherever they are needed.
You can also think of passing a handle of derived class and call the method with that.
class pointAccumulator {
public:
template<class Archive, class Derived>
void serialize(Archive & ar, const unsigned int version, Derived &derived)
{ // optional ^^^^^^^^^^^^^^^^^
// call virtual methods to derived from here
// optional: for non-virtual method, you can use derived class handle
}
};
The only thing which you need to take care is that, whatever non-virtual methods you call inside serialize()
using derived
handle --> should be of same name in all the children classes from pointAccumulator
, irrespective of what they do inside.
回答4:
In fact, I'll make my comment an answer:
~/src/snips$ cat serializer-demo.cc
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>
typedef boost::archive::polymorphic_iarchive bpi;
typedef boost::archive::polymorphic_oarchive bpo;
typedef const unsigned int cui;
struct ABC
{
virtual void serialize(bpi &ar, cui v) = 0;
virtual void serialize(bpo &ar, cui v) = 0;
};
struct A : ABC
{
void serialize(bpi &ar, cui v ) { ar & data; }
void serialize(bpo &ar, cui v ) { ar & data; }
int data;
bool operator==(const A & rhs) const
{ return data == rhs.data; }
A(int data=0) : data(data) {}
};
#include <sstream>
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/archive/polymorphic_binary_iarchive.hpp>
#include <boost/archive/polymorphic_binary_oarchive.hpp>
int main(int argc, char* argv[])
{
const A a(1);
const ABC &abc = a;
A a1;
ABC &abc1 = a1;
{
std::stringstream ss;
{
boost::archive::polymorphic_text_oarchive oa(ss);
boost::archive::polymorphic_oarchive & oa_interface = oa;
oa_interface << abc;
}
{
boost::archive::polymorphic_text_iarchive ia(ss);
ia >> abc1;
}
}
if(! (a == a1))
return 1;
{
std::stringstream ss;
{
boost::archive::polymorphic_binary_oarchive oa(ss);
oa << abc;
}
{
boost::archive::polymorphic_binary_iarchive ia(ss);
boost::archive::polymorphic_iarchive & ia_interface = ia;
ia_interface >> abc1;
}
}
if(! (a == a1))
return 1;
return 0;
}
~/src/snips$ make -B serializer-demo
g++ -o bin/serializer-demo --std=c++0x -g -O -march=native -pipe -Wall -Wno-parentheses -lboost_serialization serializer-demo.cc
~/src/snips$ type -pa serializer-demo
./bin/serializer-demo
~/src/snips$ serializer-demo
~/src/snips$ echo $?
0
~/src/snips$
回答5:
So I have an interesting way of faking virtualism for templated functions. Faking a virtual templated function c++
The basic motivation might be applied here if you need this enforced in the hierarchy, but you can utilize boost meta programming library to allow a run-time solution for this problem.
来源:https://stackoverflow.com/questions/10490245/virtual-functions-and-template-clash