Форум программистов, компьютерный форум, киберфорум
Наши страницы
Boost C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
Avazart
Эксперт С++
7791 / 5691 / 560
Регистрация: 10.12.2010
Сообщений: 25,918
Записей в блоге: 17
1

Boost_serialization

06.10.2014, 20:16. Просмотров 651. Ответов 7
Метки нет (Все метки)

Правильно ли я понимаю что boost/serialization не позволяете сериализовать вектор из указателей на базовый класс?

C++
1
2
3
4
5
class A{/* код класса, включая код сериализации*/};
class B: public A {/*...*/}
class C: public A {/*...*/}
 
std::vector<A*> v; /* тут могут хранится указатели на A, B, C */
0
Лучшие ответы (1)
ForEveR
В астрале
Эксперт С++
8002 / 4760 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
06.10.2014, 20:59 2
Avazart, Точно помню, что позволяет. Только слегка сложнее.
http://www.boost.org/doc/libs/1_56_0/libs/serialization/doc/index.html
Сначала читаем это, а я попробую вспомнить как правильно это реализовать.
Вспомнил: http://www.boost.org/doc/libs/1_48_0...erivedpointers читаем тут и вообще все, ибо полезная инфа.

Добавлено через 16 минут
Простенький пример: http://coliru.stacked-crooked.com/a/083580e4bb54d929
1
Avazart
Эксперт С++
7791 / 5691 / 560
Регистрация: 10.12.2010
Сообщений: 25,918
Записей в блоге: 17
06.10.2014, 21:51  [ТС] 3
Ну я сразу вышел на первую ссылку, успел накатать такой код:
Код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
class A
{
    public:
        A(){};
        A(std::string name):name_(name){}
        virtual ~A(){}
 
        std::string name(){ return name_; };
 
        virtual std::string description(){ return name_; }
 
    private:
 
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive &ar,const unsigned int version)
        {
             ar & name_;
        }
 
        std::string name_;
};
 
class B: public A
{
    public:
        B():A(){}
        B(std::string name,int intValue)
             :A(name),
             intValue_(intValue)
        {}
 
        std::string description()
        {
         std::stringstream ss;
         ss<< name() <<" "<<intValue_;
         return ss.str();
        }
 
        int intValue(){ return intValue_; }
 
    private:
 
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive &ar,const unsigned int version)
        {
             ar & boost::serialization::base_object<A>(*this);
             ar & intValue_;
        }
 
        int intValue_;
};
 
 
class C: public A
{
    public:
        C():A(){}
        C(std::string name,double doubleValue)
         : A(name),
             doubleValue_(doubleValue)
        {}
 
        std::string description()
        {
            std::stringstream ss;
            ss<< name() <<" "<<doubleValue_;
            return ss.str();
        }
 
        double doubleValue(){ return doubleValue_; }
 
    private:
 
        friend class boost::serialization::access;
        template<class Archive>
        void serialize(Archive &ar,const unsigned int version)
        {
             ar & boost::serialization::base_object<A>(*this);
             ar & doubleValue_;
        }
 
        double doubleValue_;
};
 
void save()
{
    std::ofstream file("archiv.txt");
    boost::archive::text_oarchive oa(file);
 
    A* a= new A("A1");
    oa<<a;
    delete a;
 
    /*В*/  A* b= new B("B1",10);
    oa<<b;
    delete b;
}
 
void load()
{
    std::ifstream file("archiv.txt");
    boost::archive::text_iarchive ia(file);
 
    A* a;
    ia>>a;
    std::cout<< a->description()<<std::endl;
    delete a;
 
    B* b;
    ia>>b;
    std::cout<< b->description()<<std::endl;
    delete b;
}
 
int main()
{
    save();
    load();
 
    getchar();
    return 0;
}

А вот описание register_type не видел.

Добавлено через 21 минуту
Добавил register_type

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void save()
{
    std::ofstream file("archiv.txt");
    boost::archive::text_oarchive oa(file);
 
    //oa.register_type<A>();  ???
    oa.register_type<B>();
    oa.register_type<C>();
 
    A* a= new A("A1");
    oa<<a;
    delete a;
 
    A* b= new B("B1",10);
    oa<<b;
    delete b;
 
    A* c= new C("C1",3.14);
    oa<<c;
    delete c;
}
 
void load()
{
    std::ifstream file("archiv.txt");
    boost::archive::text_iarchive ia(file);
 
 // ia.register_type<A>();  ???
    ia.register_type<B>();
    ia.register_type<C>();
 
    A* a;
    ia>>a;
    std::cout<< a->description()<<std::endl;
    delete a;
 
    B* b;
    ia>>b;
    std::cout<< b->description()<<std::endl;
    delete b;
 
    C* c;
    ia>>c;
    std::cout<< c->description()<<std::endl;
    delete c;
}
Получаю неадекватный вывод:
A1
B1 10
3.14
Т.е. "C1" cъело...
0
ForEveR
В астрале
Эксперт С++
8002 / 4760 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
06.10.2014, 23:01 4
Лучший ответ Сообщение было отмечено Убежденный как решение

Решение

Avazart, Ищите в чем проблема... http://coliru.stacked-crooked.com/a/4ee29ac63cd3fad6 выводит

A1
B1 10
C1 3.14
П.С. при сейве, на удаление указателя ровно после записи получал исключение pointer_conflict, поэтому перенес в конец функции.
1
Avazart
Эксперт С++
7791 / 5691 / 560
Регистрация: 10.12.2010
Сообщений: 25,918
Записей в блоге: 17
06.10.2014, 23:20  [ТС] 5
Цитата Сообщение от ForEveR Посмотреть сообщение
П.С. при сейве, на удаление указателя ровно после записи получал исключение pointer_conflict, поэтому перенес в конец функции.
Да похоже в этом была проблема. Вероятно в реальном коде нужно использовать смарт поинтеры чтобы такое не наблюдать.
Тестил в С++BuilderXE3 он не ругался на удаление, нужно будет как нибудь в MSVC попробовать.

Да и обязательно регистрировать базовый класс?

Добавлено через 7 минут
Я заглянул в файл и не увидел там имени классов, так что вероятно сохраняется какой нибудь индекс определяющий тип класса, из чего вероятно можно предположить что индексы могут зависеть от порядка регистрации классов, а значит могут быть проблемы при чтении/сохранении данных разными программами из одного файла, так ?
0
ForEveR
В астрале
Эксперт С++
8002 / 4760 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
06.10.2014, 23:26 6
Avazart, Нет, необязательно.
Как там сохраняется - детали реализации, не более того. Какие могут быть проблемы, конкретнее пожалуйста.
0
Avazart
Эксперт С++
7791 / 5691 / 560
Регистрация: 10.12.2010
Сообщений: 25,918
Записей в блоге: 17
07.10.2014, 00:40  [ТС] 7
Цитата Сообщение от ForEveR Посмотреть сообщение
Как там сохраняется - детали реализации, не более того.
Оно то так но во первых интересно что там под капотом, во вторых что под капотом определяет возможные проблемы.
Цитата Сообщение от ForEveR Посмотреть сообщение
Какие могут быть проблемы, конкретнее пожалуйста.
Если полагаться на предположение что boost записывает id класса(в порядке регистрации классов, к примеру) то к примеру A=0, B=1, C=2 то очевидно что эти значения должны(ну и порядок регистрации) совпадать в разных приложения которые должны иметь возможность работать с одним файлом. Иначе что записало в файл одно приложение не сможет прочитать другое.

Добавлено через 1 час 3 минуты
Можно проделать такой тест с моим кодом:
1. Запустить программу что бы создался файл и закрыт программу.
2. Закомментировать строчку с ф-цией save() что бы при следующем запуске программы только читались предыдущие данные с файла

C++
1
2
3
4
5
int main()
{
    //save();
    load();
// ...
А затем сменить порядок регистрации классов в функции load();

C++
1
2
ia.register_type<C>();
ia.register_type<B>();
И перекомпилировать/запустить программу- лично у меня выбивает ошибку при чтении, думаю это подтверждает мое предположение.
0
ForEveR
В астрале
Эксперт С++
8002 / 4760 / 653
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
07.10.2014, 10:44 8
Avazart, Возможно. Не все в этом жизни идеально. Можете посмотреть на то как это действительно реализовано в сорцах буста.

Добавлено через 36 минут
В общем и целом все именно так:

C++
1
2
3
4
5
6
7
8
9
inline const basic_oarchive_impl::cobject_type &
basic_oarchive_impl::register_type(
    const basic_oserializer & bos
){
    cobject_type co(cobject_info_set.size(), bos);
    std::pair<cobject_info_set_type::const_iterator, bool>
        result = cobject_info_set.insert(co);
    return *(result.first);
}
Где cobject_type
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    struct cobject_type
    {
        const basic_oserializer * m_bos_ptr;
        const class_id_type m_class_id;
        bool m_initialized;
        cobject_type(
            std::size_t class_id,
            const basic_oserializer & bos
        ) :
            m_bos_ptr(& bos),
            m_class_id(class_id),
            m_initialized(false)
        {}
        // ...
    }
А cobject_info_set

C++
1
2
    typedef std::set<cobject_type> cobject_info_set_type;
    cobject_info_set_type cobject_info_set;
Так что да, порядок регистрации имеет значение.
1
07.10.2014, 10:44
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru