Virtual functions and template clash

匿名 (未验证) 提交于 2019-12-03 02:26:02

问题:

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 templates 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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!