3

継承階層内のクラスが仮想読み取りおよび書き込み関数を実装することを確認することで、シリアル化を実装しました。

class base
{
     ...

     virtual void read(std::istream&)=0;
     virtual void write(std::ostream&) const=0;
     virtual std::string is_a() const;
};

BEGIN_NAMESPACE_1(io)
    SERIALISE(base)
END_NAMESPACE_1

ここで、マクロ "SERIALISE" は "serialise" および "deserialise" 関数のオーバーロードを実装して、基本クラス ポインターを介した簡単な i/o を可能にします。

#define SERIALISE(TYPE)\
void deserialise( boost::shared_ptr<TYPE>& dat, std::istream& ifs )\
{\
    std::string type;\
    read(type, ifs);\
\
    dat = TYPE::make_##TYPE(type);\
    dat->read(ifs);\
}\
\
void serialise( const boost::shared_ptr<TYPE>& dat, std::ofstream& ofs )\
{\
    write(dat->is_a(), ofs);\
    dat->write(ofs);\
}

ただし、基本クラスに純粋な仮想関数が含まれている場合、おそらくコンパイラが抽象をインスタンス化しようとするため、「抽象型「ベース」のオブジェクトを次の関数が純粋であるため、割り当てられません...」というコンパイラ エラーが発生します。クラス名がマクロ呼び出しに渡されるときの基本クラス。この I/O 設計を救済する方法はありますか?

4

1 に答える 1

1

抽象基本クラスをインスタンス化することも、関数への値パラメーターとして使用することもできません。

テンプレートの明示的な shared_ptr(Y * p); 要件: p は T * に変換可能でなければなりません。Y は完全な型でなければなりません。式 delete p は整形式である必要があり、未定義の動作を呼び出してはならず、例外をスローしてはなりません。

効果: ポインター p を所有する shared_ptr を構築します。

事後条件: use_count() == 1 && get() == p.

スロー: std::bad_alloc、またはメモリ以外のリソースを取得できなかった場合の実装定義の例外。

例外の安全性: 例外がスローされた場合、delete p が呼び出されます。

注: p は、C++ の new 式を介して割り当てられたオブジェクトへのポインターであるか、0 でなければなりません。p が 0 の場合でも、使用カウントが 1 である事後条件は保持されます。値が 0 のポインターで delete を呼び出しても問題はありません。

この場合、コンパイラはテンプレート shared_ptr をインスタンス化できないため、型 TYPE の値を内部に持つものとして解決する必要はありません。

于 2012-10-22T15:30:03.033 に答える