4

pointAccumulatorの抽象基本クラスがあります。この抽象ベースには、すべてのポイントの平均を返す関数などのメソッドが入力されます。これら2つのクラスの例を以下に示します。

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_;
};

コードでわかるように、これらのタイプを保存するためにブーストシリアル化も使用したいと思います。ファクトリパターンを使用して、pointAccumulatorタイプを次のように呼び出すと思います。

lala *a1 = new lalaLower();

私の問題は、このように呼び出すと、テンプレート化されたシリアル化メソッドにアクセスできないことです。また、c ++では許可されていないため、抽象クラスにテンプレートクラスを含めることはできません。これを回避する方法はありますか?

編集:

私はシリアル化のための非侵入的な方法を検討しましたが、それはheights_を公開する必要があり、これは理想的ではなく、優れたプログラミングスタイルでもありません。フレンドクラスまたは関数を使用するメソッドは、基本クラスを抽象化したまま、変数にアクセスしてクラスに侵入できる可能性があると思いましたか?誰かがこれがどのように機能するか説明できますか?

4

5 に答える 5

1

実際、私は私のコメントを答えにします:

~/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$ 
于 2012-05-14T18:25:20.063 に答える
1

ご存知かもしれませんがtemplate、 とvirtualメソッドは連動しません。

メソッドを削除して本体にmeanAccumulator::serialize()追加し、必要な場所で内部の関数を呼び出すことをお勧めします。 派生クラスのハンドルを渡して、それでメソッドを呼び出すことも考えられます。class pointAccumulatorvirtual

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
  }
};

注意が必要な唯一のことは、内部でhandle -->serialize()を使用して呼び出す非仮想メソッドは、内部で何をするかに関係なく、 のderivedすべての子クラスで同じ名前にする必要があるということです。pointAccumulator

于 2012-05-11T04:29:24.220 に答える
1

したがって、テンプレート化された関数の仮想化を偽装する興味深い方法があります。仮想テンプレート関数 c++ の偽造

階層内でこれを強制する必要がある場合は、基本的な動機がここに適用される可能性がありますが、ブースト メタ プログラミング ライブラリを利用して、この問題のランタイム ソリューションを可能にすることができます。

于 2012-05-16T04:42:16.710 に答える
1

Archiveこの方法または別の方法で型パラメーターをポリモーフィック階層にラップしないと、それを行うことはできないと思います。

それはBoost.Serialization あなたのためにそれを行うようですが

于 2012-05-07T23:29:54.577 に答える