5

Tôi đang cố gắng sắp xếp các cấu trúc dữ liệu của mình để ghi chúng vào một ổ cắm tcp.Lỗi khi sắp xếp một lớp trừu tượng bằng cách tăng

Cho đến nay tôi nhận thấy rằng sự cố của tôi là sự tuần tự hóa. Tôi thậm chí đã cố gắng sử dụng

BOOST_SERIALIZATION_ASSUME_ABSTRACT(T) 

nhưng tôi không thể tìm thấy bất kỳ ví dụ làm việc nào tương tự như chương trình của tôi và cách triển khai đúng cách.

Dưới đây là một số trong các liên kết mà tôi đã truy cập:

cấu trúc dữ liệu của tôi là một chút phức tạp hơn sau đó này nhưng chúng ta hãy giả định rằng tôi có cấu trúc sau đây

Coordinate.h

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

class Coordinate { 
public: 
    Coordinate() {} 
    Coordinate(int c) : c(c) {} 
    int get(void) { return c; } 
    std::string toString(void); 
private: 
    int c; 
    friend class boost::serialization::access; 
    template<typename Archive> 
    void serialize(Archive &ar, const unsigned int version) { 
     ar & this->c; 
    } 
}; 

Move.h

class Coordinate; 

#include "Coordinate.h" 

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

class Move { 
public: 
    Move() {} 
    ~Move() {} 
    Coordinate* getCoordinate(void) {return this->destination; } 
    virtual bool isJump(void) = 0; 
protected: 
    Coordinate *destination; 
private: 
    friend class boost::serialization::access; 
    template<typename Archive> 
    void serialize(Archive &ar, const unsigned int version) { 
     ar & this->destination; 
    } 
}; 

MoveNormal.h

class Coordinate; 

#include "Move.h" 
#include "Coordinate.h" 

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

class MoveNormal : public Move { 
public: 
    MoveNormal() {} 
    MoveNormal(Coordinate *destination) { this->destination = destination; } 
    ~MoveNormal() {} 
    virtual bool isJump(void); 
private: 
    friend class boost::serialization::access; 
    template<typename Archive> 
    void serialize(Archive &ar, const unsigned int version) { 
     ar & boost::serialization::base_object<Move>(*this); 
    } 
}; 

Các phương pháp ảo được quy định tại đây.

MoveNormal.cpp

#include "MoveNormal.h" 

bool MoveNormal::isJump(void) { 
    return false; 
} 

main.cpp của tôi trông như thế này:

#include "Coordinate.h" 
#include "Move.h" 
#include "MoveNormal.h" 

#include <fstream> 

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

int main(int argc, char *argv[]) { 
    Coordinate *c = new Coordinate(10); 
    // This runs OK 
    /* 
    { 
     std::ofstream ofs("f.txt"); 
     boost::archive::text_oarchive oa(ofs); 
     oa << c; 
    } 
    Coordinate *d; 
    { 
     std::ifstream ifs("f.txt"); 
     boost::archive::text_iarchive ia(ifs); 
     ia >> d; 
    } 
    std::cout << "c.get(): " << c->get() << std::endl; 
    std::cout << "d.get(): " << d->get() << std::endl; 
    */ 

    // This is where I get my error 
    Move *m = new MoveNormal(c); 
    { 
     std::ofstream ofs("f.txt"); 
     boost::archive::text_oarchive oa(ofs); 
     oa << m; // Line where the error occurs 
    } 
    return 0; 
} 

Nhưng khi tôi chạy chương trình tôi nhận được lỗi sau:

Unhandled exception at 0x76dbb9bc in Test.exe: Microsoft C++ exception: boost::archive::archive_exception at memory location 0x001df078..

tôi m sử dụng VS2010 và Tăng 1.48.0.

+0

khai báo toán tử quá tải << như một người bạn của lớp, sau đó thực hiện nó, Xem xét cấu trúc dữ liệu của bạn chỉ bao gồm giá trị int. làm. Nếu bạn cần truyền điều này qua một socket, chỉ cần reinterpret_cast int vào char * và gửi nó qua socket;) – johnathon

+0

Thực tế là cấu trúc dữ liệu của tôi không chỉ có một int. Ví dụ trên đây là một cấu trúc đơn giản được tạo ra chỉ dành cho trường hợp này. Hãy xem xét rằng bên trong cấu trúc của tôi tôi có con trỏ đến các lớp khác và container stl. Cho đến nay tôi nghĩ rằng tôi đã tìm ra cách để làm cho nó hoạt động. Tôi chỉ đang thử nghiệm nó trong dự án của tôi và tôi sẽ đăng giải pháp ở đây càng sớm càng tốt. – ealves

Trả lời

7

Đây là một chút lạ nhưng tôi sẽ trả lời câu hỏi của riêng tôi. Tôi chỉ tìm ra cách làm ví dụ của tôi ở trên công việc.

Đây là giải pháp. Mỗi lần chúng ta cần phải serialize một lớp kế thừa các thuộc tính từ lớp khác chúng ta cần phải sử dụng macro:

BOOST_CLASS_EXPORT(T) 

Theo boost serialization doc

BOOST_CLASS_EXPORT in the same source module that includes any of the archive class headers will instantiate code required to serialize polymorphic pointers of the indicated type to the all those archive classes. If no archive class headers are included, then no code will be instantiated.

Note that the implemenation of this functionality requires that the BOOST_CLASS_EXPORT macro appear after and the inclusion of any archive class headers for which code is to be instantiated.

Vì vậy, trong trường hợp của tôi tập main.cpp của tôi bây giờ là:

#include <fstream> 

#include <boost\archive\text_iarchive.hpp> 
#include <boost\archive\text_oarchive.hpp> 
#include <boost\serialization\export.hpp> 

#include "Coordinate.h" 
#include "Move.h" 
#include "MoveNormal.h" 
BOOST_CLASS_EXPORT(MoveNormal) 

int main(int argc, char *argv[]) { 
    Coordinate *c = new Coordinate(150); 
    Move *m = new MoveNormal(c); 
    std::cout << "m.getDestination().get(): " << m->getDestination()->get() << std::endl; 
    { 
     std::ofstream ofs("f.txt"); 
     boost::archive::text_oarchive oa(ofs); 
     oa << m; 
    } 

    Move *n; 
    { 
     std::ifstream ifs("f.txt"); 
     boost::archive::text_iarchive ia(ifs); 
     ia >> n; 
    } 
    std::cout << "n.getDestination().get(): " << n->getDestination()->get() << std::endl; 
    return 0; 
} 

Chỉ cần đảm bảo rằng bạn bao gồm tất cả lưu trữ tăng mà bạn cần trước khi bạn sử dụng MACRO xuất.

Để hoàn thành dự án của mình ngoài việc tuần tự hóa, tôi cần phải ghi chúng vào ổ cắm tcp bằng cách sử dụng boost :: asio.

Vì vậy, chúng ta hãy giả định rằng tôi có một tiêu đề kết nối như this one và rằng bây giờ tôi đã lớp khác được gọi MoveJump quy định tại MoveJump.h tôi

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

#include "Coordinate.h" 
#include "Move.h" 

class MoveJump : public Move { 
public: 
    MoveJump() {} 
    MoveJump(Coordinate *c) { this->destinatio = c; } 
    ~MoveJump() {} 
    virtual bool isJump(void); 
private: 
    friend class boost::serialization::access; 
    template<typename Archive> 
    void serializize(Archive &ar, const unsigned int version) { 
     ar & boost::serialization::base_object<Move>(*this); 
    } 
}; 

Bây giờ để serialize các cấu trúc nhìn chính của tôi như thế này

Bí quyết là đăng ký các lớp sẽ được sắp xếp theo thứ tự khi chúng ta có con trỏ đến lớp cơ sở.

Nếu bên trong Move.h tôi có nhiều gợi ý cho các lớp cơ sở khác mà tôi làm trong dự án của mình, chúng ta cần đưa vào tất cả các tiêu đề chính và đăng ký tất cả các lớp có thể mở rộng lớp cơ sở.

Tôi hy vọng điều này sẽ giúp ai đó có thể gặp sự cố tương tự trong tương lai.

Hãy thoải mái trình bày các giải pháp khả thi mới.

Cảm ơn

0

nói chung, bạn chỉ có thể sử dụng BOOST_CLASS_EXPORT đăng ký tất cả các lớp học, hoặc bạn có thể sử dụng BOOST_SERIALIZATION_ASSUME_ABSTRACT cho lớp siêu, và sử dụng viên chức năng register_type của "archive" với nhau. xem: How to serialize derived template classes with Boost.serialize? để biết chi tiết (xin lỗi vì tiếng anh nghèo của tôi :))