2016-02-13 5 views
6

मेरे पास चार वर्ग (A, B, C और D) क्लासिक डायमंड पैटर्न और Container कक्षा के बाद unique_ptr<A> है। मैं cereal क्रमबद्धता लाइब्रेरी का उपयोग करके इन कक्षाओं को क्रमबद्ध करना चाहता हूं।आभासी विरासत और बहुरूपता: क्या अनाज पुस्तकालय ऑब्जेक्ट लेआउट के साथ गड़बड़ कर रहा है?

struct A {int f1; int f2; int f3} 

struct B : public virtual A { 
    template<typename Archive> 
    inline void save(Archive& ar) const { 
     std::cerr << "Saving Obj: " << this << std::endl; 
     std::cerr << "This: " << &(this->f1) << " " 
      << &(this->f2) << " " << &(this->f3) << std::endl; 
     std::cerr << "This: " << this->f1 << " " 
      << this->f2 << " " << this->f3 << std::endl; 
    }; 
} 
}; 

struct C : public virtual A {}; 

struct D : public B, public C {}; 

#include <cereal/archives/binary.hpp> 
CEREAL_REGISTER_TYPE(B); 
CEREAL_REGISTER_TYPE(C); 
CEREAL_REGISTER_TYPE(D); 

struct Container { 
    std::unique_ptr<A> obj; 

    template<typename Archive> 
    inline void save(Archive& ar) const { 
     std::cerr << "Saving Container" << std::endl; 
     std::cerr << "Obj Addr: " << obj.get() << std::endl; 
     std::cerr << "Obj: " << &(obj->f1) << " " << &(obj->f2) 
      << " " << &(pq->f3) << std::endl; 
     std::cerr << "Obj: " << " " << pq->sq_count << " " << pq->sq_bits 
      << " " << pq->dim << std::endl; 
     ar(obj); // Call serialization for obj, ie B.save(...) 
    } 
} 

सभी वर्गों अनाज save और load कार्यों है, लेकिन मैं केवल, B और Container के लिए उन्हें शामिल के रूप में वे केवल इस उदाहरण में प्रयुक्त होते हैं।

मैं इस प्रकार इन कक्षाओं का उपयोग करें:

std::unique_ptr<A> obj(new B); 
obj->f1 = 8; 
obj->f2 = 8; 
obj->f3 = 128; 
std::unique_ptr<Container> db(new Container); 
db.obj = std::move(obj); 

std::ofstream out_file(out_filename); 
cereal::BinaryOutputArchive out_archive(out_file); 
out_archive(db); 

और मैं निम्नलिखित उत्पादन प्राप्त करें:

Saving Container 
Obj Addr: 0x23d2128 
Obj: 0x23d2130 0x23d2134 0x23d2138 // Fields adresses (f1,f2,f3) 
Obj: 8 8 128 // Fields values 
Saving Obj: 0x23d2128 // Same object 
This: 0x23d2118 0x23d211c 0x23d2120 // Different field adresses ! 
This: 4293296 0 37569440 // Garbage 

मेरे सवाल यह है: यह संभावना है कि इस अनाज में एक बग है, या वहाँ है ऐसा कुछ जो मुझे आभासी विरासत से नहीं मिलता है?

क्या यह उम्मीद की जाती है कि किसी दिए गए ऑब्जेक्ट के फ़ील्ड के पते कभी भी C++ प्रोग्राम में बदल जाएंगे?

+0

'ar (obj)' कॉल 'B :: save (ar)' क्यों होगा? – aschepler

+0

@aschepler अनाज पुस्तकालय यह करता है: http://uscilab.github.io/cereal/serialization_functions.html – Xion345

उत्तर

1

मैं अनाज की वर्तमान विकास शाखा पर आपकी त्रुटि पुन: उत्पन्न नहीं कर सकता, हालांकि मैं इसे वर्तमान मास्टर (1.1.2) पर पुन: उत्पन्न कर सकता हूं। मैं अपना कोड संशोधित किया वास्तव में संकलित करने के लिए:

#include <cereal/types/memory.hpp> 
#include <cereal/types/polymorphic.hpp> 
#include <cereal/archives/json.hpp> 
#include <fstream> 
#include <iostream> 

struct A { 
    int f1; int f2; int f3; 
    virtual ~A() {} 

    template<typename Archive> 
    void serialize(Archive & ar) 
    { 
     std::cerr << "Saving A Obj: " << this << std::endl; 
     std::cerr << "This: " << &(this->f1) << " " 
     << &(this->f2) << " " << &(this->f3) << std::endl; 
     std::cerr << "This: " << this->f1 << " " 
     << this->f2 << " " << this->f3 << std::endl; 
    }; 
}; 

struct B : public virtual A { 
    template <class Archive> 
    void serialize(Archive & ar) 
    { 
    std::cerr << "Saving B Obj: " << this << std::endl; 
    std::cerr << "This: " << &(this->f1) << " " 
     << &(this->f2) << " " << &(this->f3) << std::endl; 
    std::cerr << "This: " << this->f1 << " " 
     << this->f2 << " " << this->f3 << std::endl; 

    ar(cereal::virtual_base_class<A>(this)); 
    } 

    virtual ~B() {} 
}; 

CEREAL_REGISTER_TYPE(B); 

struct Container { 
    std::unique_ptr<A> obj; 

    template<typename Archive> 
     void serialize(Archive & ar) 
    { 
     std::cerr << "Saving Container (A)" << std::endl; 
     std::cerr << "Obj Addr: " << obj.get() << std::endl; 
     std::cerr << "Obj: " << &(obj->f1) << " " << &(obj->f2) 
      << " " << &(obj->f3) << std::endl; 

     ar(obj); // Call serialization for obj, ie B.save(...) 
    } 
}; 

int main() 
{ 
    std::unique_ptr<A> ptr(new B()); 
    ptr->f1 = 8; 
    ptr->f2 = 8; 
    ptr->f3 = 128; 
    std::unique_ptr<Container> db(new Container()); 
    db->obj = std::move(ptr); 

    std::stringstream ss; 
    { 
    cereal::JSONOutputArchive out_archive(ss); 
    out_archive(db); 
    } 

    std::cout << ss.str() << std::endl; 
} 

1.1.2 के साथ उत्पादन:

Saving Container (A) 
Obj Addr: 0x1738d78 
Obj: 0x1738d80 0x1738d84 0x1738d88 
Saving B Obj: 0x1738d78 
This: 0x1738d78 0x1738d7c 0x1738d80 
This: 4316664 0 8 
Saving A Obj: 0x1738d70 
This: 0x1738d78 0x1738d7c 0x1738d80 
This: 4316664 0 8 
{ 
    "value0": { 
     "ptr_wrapper": { 
      "valid": 1, 
      "data": { 
       "value0": { 
        "polymorphic_id": 2147483649, 
        "polymorphic_name": "B", 
        "ptr_wrapper": { 
         "valid": 1, 
         "data": { 
          "value0": {} 
         } 
        } 
       } 
      } 
     } 
    } 
} 

उत्पादन का उपयोग कर विकसित:

Saving Container (A) 
Obj Addr: 0x1f74e18 
Obj: 0x1f74e20 0x1f74e24 0x1f74e28 
Saving B Obj: 0x1f74e10 
This: 0x1f74e20 0x1f74e24 0x1f74e28 
This: 8 8 128 
Saving A Obj: 0x1f74e18 
This: 0x1f74e20 0x1f74e24 0x1f74e28 
This: 8 8 128 
{ 
    "value0": { 
     "ptr_wrapper": { 
      "valid": 1, 
      "data": { 
       "value0": { 
        "polymorphic_id": 2147483649, 
        "polymorphic_name": "B", 
        "ptr_wrapper": { 
         "valid": 1, 
         "data": { 
          "value0": {} 
         } 
        } 
       } 
      } 
     } 
    } 
} 

तो जो कुछ भी इस समस्या पैदा कर रहा था संभावना ठीक हो गई है अनाज की वर्तमान विकास शाखा में, जो निकट भविष्य में 1.2 के रूप में जारी किया जाएगा।

संबंधित मुद्दे