2016-03-01 56 views
1

我試圖反序列化對象不具有默認構造函數。我已經看到,你可以通過將存檔傳遞給構造函數來完成此操作。但是,當我這樣做時,它似乎沒有正確讀取數據?這裏是一個例子 - Works()應該輸出「1 2」(使用默認構造函數和操作符>>),但DoesntWork()輸出「0 0」。我已經步入了一切,似乎一切都被恰當地調用了。任何人都可以解釋這兩個函數之間的區別嗎?反序列化構造函數不讀取數據正確

#include <fstream> 

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

class Point 
{ 
private: 
    friend class boost::serialization::access; 

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

public: 
    template<class TArchive> 
    Point(TArchive& archive) 
    { 
     serialize(archive, 0); 
    } 

    Point(){} // Only provided to test Works() 

    Point(const float x, const float y) : mX(x), mY(y) { } 

    float mX = 4; 
    float mY = 5; 
}; 

void Works() 
{ 
    std::cout << "Works():" << std::endl; 
    Point p(1,2); 

    std::ofstream outputStream("test.archive"); 
    boost::archive::text_oarchive outputArchive(outputStream); 
    outputArchive << p; 
    outputStream.close(); 

    // read from a text archive 
    std::ifstream inputStream("test.archive"); 
    boost::archive::text_iarchive inputArchive(inputStream); 
    Point pointRead; 
    inputArchive >> pointRead; 

    std::cout << pointRead.mX << " " << pointRead.mY << std::endl; 
} 

void DoesntWork() 
{ 
    std::cout << "DoesntWork():" << std::endl; 
    Point p(1,2); 

    std::ofstream outputStream("test.archive"); 
    boost::archive::text_oarchive outputArchive(outputStream); 
    outputArchive << p; 
    outputStream.close(); 

    std::ifstream inputStream("test.archive"); 
    boost::archive::text_iarchive inputArchive(inputStream); 
    Point pointRead(inputArchive); 

    std::cout << pointRead.mX << " " << pointRead.mY << std::endl; 
} 

int main() 
{ 
    Works(); // Output "1 2" 
    DoesntWork(); // Output "0 0" 
    return 0; 
} 
+0

一個例子是不是構造_serialising_而比_deserialising_? 'serialize(archive,0)'應該如何反序列化? –

+0

@PreferenceBean序列化或反序列化取決於TArchive如何定義操作員 – stijn

回答

1

你不應該直接調用serialize方法:operator >>爲存檔做方式不僅僅是打電話serialize以上;根據檔案的種類首先需要,或通過檢查裏面有什麼test.archive加載的前導等,您可以通過使用調試器逐句通過驗證這一點,它是一樣的東西

22 serialization::archive 12 0 0 1.000000000e+000 2.000000000e+000 

構建後如此吧text_iarchive前兩個電話operator &將碰巧看到那些2 0在那裏,而不是實際的數據。

你的構造應該是:

template<class TArchive> 
Point(TArchive& archive) 
{ 
    archive >> *this; 
} 

編輯這裏有一個如何使用SFINAE以確保拷貝構造函數仍然可以調用

Point(const Point& rh) : 
    mX(rh.mX), 
    mY(rh.mY) 
{ 
} 

template<class TArchive> 
Point(TArchive& archive, 
     std::enable_if_t< !std::is_same< TArchive, Point >::value >* = nullptr) 
{ 
    archive >> *this; 
} 
+0

我也注意到這些額外的0的,但我認爲他們是某種頭的。我希望標題自動被自動分析,但現在我明白了它的區別 - 謝謝! –

+0

如果我已經有一個模板化的構造函數,通常我會創建一個命名的靜態「構造函數」,但在這種情況下,我需要訪問'this'指針。在這種情況下的最佳實踐建議? –

+0

我不能僅僅命名其他構造函數,因爲例如,拷貝構造函數必須是特定的簽名。 –