2016-03-25 17 views
1

(Bu soru this one'a çok benziyor, ancak bu seferserileştirici kurucuyu Child başlatma listesinde çağırıyorum). Bir Child hiçbir yeni veri Serileştirilecek ekleyen bir durumda Yapılandırıcı hiyerarşisini serileştirme

, Parent ben Child doğrudan yanı Parent nesne seri edebilmek istiyorum bir varsayılan kurucu ve yok çocuk ne de ebeveyn varsayılan kurucuya sahip, biz başlatma listesinde (aynı zamanda deserializing yapıcısı kullanılarak) çocuk deserializing yapıcı ebeveyn başlatır aşağıdaki deseni, kullanmalıdır gibi görünüyor:

#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 

#include <fstream> 

class Parent 
{ 
public: 
    double mParentData; 

    Parent(const double data) : mParentData(data) {} 

    template<typename TArchive> 
    Parent(TArchive& archive) 
    { 
     archive >> *this; 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     archive & mParentData; 
    } 
}; 

class Child : public Parent 
{ 
public: 

    Child(const double data) : Parent(data) {} 

    template<typename TArchive> 
    Child(TArchive& archive) : Parent(archive) 
    { 
     // Do nothing, as the only data to read is in Parent 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     // Let the parent do its serialization 
     archive & boost::serialization::base_object<Parent>(*this); 

     // Nothing else to do, as the only data to read/write is in Parent 
    } 
}; 

int main() 
{ 
    Child child(1.2); 

    { 
     std::ofstream outputStream("test.txt"); 
     boost::archive::text_oarchive outputArchive(outputStream); 

     outputArchive << child; 
     outputStream.close(); 
    } 

    { 
     std::ifstream inputStream("test.txt"); 
     boost::archive::text_iarchive inputArchive(inputStream); 
     Child childRead(inputArchive); 

     std::cout << "childRead:" << std::endl 
        << childRead.mParentData << std::endl; // Outputs 0 (expected 1.2) 
    } 

    return 0; 
} 

Yani çağrı zinciri gerekir (ve yapar) gibi görünün:

Çıktı:

  • Çocuk :: serialize()
  • Veli :: serialize()

Girdi:

  • Çocuk (arşiv)
  • Üst (arşiv)
  • .210
  • Veli :: serialize()

Ancak mParentData ben 1.2 olmasını beklediğiniz childRead yılında 0 olarak sona erer.

Hata gören var mı?

----------- DÜZENLEME -----------

olarak çocuk seri hale getirmek hiçbir ek veriye sahip durumda @stijn tarafından işaret , desen çocuk ve ebeveyn hem seri hale getirmek veriye sahip olduğunda durumda, Ancak

#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 

#include <fstream> 

class Parent 
{ 
public: 
    double mParentData; 

    Parent(const double data) : mParentData(data) {} 

    template<typename TArchive> 
    Parent(TArchive& archive) 
    { 
     archive >> *this; 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     archive & mParentData; 
    } 
}; 

class Child : public Parent 
{ 
public: 

    Child(const double data) : Parent(data) {} 

    template<typename TArchive> 
    Child(TArchive& archive) : Parent(archive) 
    { 
     // Do nothing, as the only data to read is in Parent 
    } 

}; 

int main() 
{ 
    Child child(1.2); 

    { 
     std::ofstream outputStream("test.txt"); 
     boost::archive::text_oarchive outputArchive(outputStream); 

     outputArchive << child; 
     outputStream.close(); 
    } 

    { 
     std::ifstream inputStream("test.txt"); 
     boost::archive::text_iarchive inputArchive(inputStream); 
     Child childRead(inputArchive); 

     std::cout << "childRead:" << std::endl 
        << childRead.mParentData << std::endl; // Outputs 0 (expected 1.2) 
    } 

    return 0; 
} 

ve ikisi de bir varsayılan kurucu yok: biz sadece bu gibi tamamen Child den serialize() fonksiyonunu kaldırabilir Aşağıdaki gibi bir şey olması gerektiği gibi görünüyor, ama tam olarak değil. Child serileştirici yapıcıda, Parent serileştirici yapıcıyı çağırıyoruz, aynı zamanda Parent::serialize() işlevini çağıran Child::serialize() işlevini çağırıyoruz, bu nedenle Parent etkin bir şekilde Parent iki kez serivermeyi deneyecektir. Bu yanlış davranış burada gösterilmiştir: Bir şekilde gibi görünüyor

#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 

#include <fstream> 

class Parent 
{ 
public: 
    double mParentData; 

    Parent(const double data) : mParentData(data) {} 

    template<typename TArchive> 
    Parent(TArchive& archive) 
    { 
     archive >> *this; 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     archive & mParentData; 
    } 
}; 

class Child : public Parent 
{ 
public: 

    double mChildData; 

    Child(const double parentData, const double childData) : Parent(parentData), mChildData(childData) {} 

    template<typename TArchive> 
    Child(TArchive& archive) : Parent(archive) 
    { 
     archive >> *this; 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
     // Let the parent do its serialization 
     archive & boost::serialization::base_object<Parent>(*this); 

     // Do the child serialization 
     archive & mChildData; 
    } 
}; 

int main() 
{ 
    Child child(1.2, 3.4); 

    { 
     std::ofstream outputStream("test.txt"); 
     boost::archive::text_oarchive outputArchive(outputStream); 

     outputArchive << child; 
     outputStream.close(); 
    } 

    { 
     std::ifstream inputStream("test.txt"); 
     boost::archive::text_iarchive inputArchive(inputStream); 
     Child childRead(inputArchive); 

     std::cout << "childRead:" << std::endl 
        << childRead.mParentData << std::endl // Outputs 0.2 (expected 1.2) 
        << childRead.mChildData << std::endl; // Outputs 3.4 correctly 
    } 

    return 0; 
} 

biz Child deserializing kurucusundan Child::serialize() farklı bir sürümünü çağırmanız gerekir? Veyaserileştirici kurucudan çağrılırsa Parent'u Child::serialize()'dan açıkça kaldırmayacak şekilde bir bayrak ayarlayın?

template<class TArchive> 
void serialize(TArchive& archive, const unsigned int version) 
{ 
    // Let the parent do its serialization 
    Parent::serialize(archive, version); 

    // Do the child serialization 
    archive & mChildData; 
} 
+0

Belki bir şey özlüyorum ama eğer 'serialize() işlevini Çocuk'ta kaldırırsanız, beklendiği gibi çalışır. Artık serileştirecek hiçbir şey olmadığından fonksiyona gerek yok, yorumlarda kendiniz söylediğiniz gibi, ve hatta üst sınıf çağrılarının '&' ile değil 'serialize' ile yapılması gerektiğini düşünmüyordum bile , yani, aramayı çağırmanız gerekir Ana :: serileştirmek veya yükseltmek :: serialization :: serialize (arşivi, yükseltmek :: serialization :: base_object (* this), version); Parent :: serialize zaten nihayet çağıran – stijn

+0

Tam olarak doğru sen @stijn, seri hale getirmek için veri olan tek bir veli olduğunda, tamamen "Çocuk :: serialize()" kaldırmak için iyi çalışıyor. Çocuğun serileştirmek için ek veriye sahip olduğu soruna örnek bir vaka ekledim. Çocuk :: serialize() 'den' Parent :: serialize (arşivi, versiyon) 'aramayı denedim, ancak bu segfaults. (ve boost :: serialization :: serialize ile aynıdır (arşivi, boost :: serialization :: base_object (* bu), sürüm); ') –

+0

Bu durumda, Lukas'ın yanıtının gitmenin yolu olduğunu düşünüyorum. else işaretçiler/kayıt türleri, ve belgeler – stijn

cevap

0

Sana ebeveyne deserialization iletmek gerekmez inanıyoruz: Biz aşağıdakilere Child::serialize() değiştirirseniz

, bir segfault olsun. benim için

#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 

#include <fstream> 

class Parent 
{ 
public: 
    double mParentData; 

    Parent(const double data) : mParentData(data) {} 

    template<typename TArchive> 
    Parent(TArchive& archive, bool deserialize = false) 
    { 
    if (!deserialize) 
     archive >> *this; 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
    archive & mParentData; 
    } 
}; 

class Child : public Parent 
{ 
public: 

    Child(const double data) : Parent(data) {} 

    template<typename TArchive> 
    Child(TArchive& archive) : Parent(archive, true) 
    { 
    archive >> *this; 
    } 

    template<class TArchive> 
    void serialize(TArchive& archive, const unsigned int version) 
    { 
    // Let the parent do its serialization 
    archive & boost::serialization::base_object<Parent>(*this); 

    // Nothing else to do, as the only data to read/write is in Parent 
    } 
}; 

int main() 
{ 
    { 
    Child child(1.2); 
    std::ofstream outputStream("test.txt"); 
    boost::archive::text_oarchive outputArchive(outputStream); 

    outputArchive << child; 
    outputStream.close(); 
    } 

    { 
    std::ifstream inputStream("test.txt"); 
    boost::archive::text_iarchive inputArchive(inputStream); 
    Child childRead(inputArchive); 


    std::cout << "childRead:" << std::endl 
     << childRead.mParentData << std::endl; // Outputs 0 (expected 1.2) 
    } 

    return 0; 
} 

eser için kodunuzu değiştirme.

+0

Yep olduğunu onaylamak gibi görünüyor, açıkça sahip değilim ve varsayılan kurucular istemiyorum. Bu, serileştirici yapıcıları kullanmanın bütün sebebi, sadece 'arşiv >> nesnesine' yani –

+0

görüyorum. Benim yaklaşımımı kullanarak, 'Ebeveyn' sınıfında boş bir serpiştirme kurucusu hakkında ve 'Çocuk' sınıfında serileştirme mantığını koru. Gibi, 'template Çocuk (Arşiv ve arşiv): Ana (arşiv) { arşivi >> *; } '. Bu yaklaşımı kullanarak varsayılan kuşakları kaldırmak mümkündür. Düzenlenmiş gönderiye bakın. – foo

+0

Bu muhtemelen 'Child' için çalışır, ancak sonra' Parent 'doğrudan seri hale getiremez ve seri hale getiremez. (ör., “Ebeveyn veli (1.2); outArchive << parent; Üst readParent (inArchive);”) –